Station Algorithm 2

by dzejkej

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
<div id="console-log"></div>

CSS

.console-line
{
    font-family: monospace;
    margin: 2px;
}

JavaScript

const TEAMS = 6;				// number of teams
const STATIONS = 3;			// number of stations
const ROUNDS = STATIONS;	// number of rounds equal to stations should be enough

// overriding console.log, cause lazy
let console = (function() {
	const CONSOLE_LINE = "<p class=\"console-line\"></p>";
	return {
	    log: function (text) {
	        $("#console-log").append($(CONSOLE_LINE).html(text));
	    }
	};
})();

// assign teams from compositions structure to the stations
function assign(team, stations, teams, friends, three = false) {
	if (teams[team].length == STATIONS) {
		return [stations, teams];
	}
	
	for (let station = 0; station < STATIONS; station++) {
		// don't assign team to a station it was assigned to before
		if (teams[team].indexOf(station) !== -1) {
			continue;	
		}

		for (let round = 0; round < ROUNDS; round++) {
			// check if any of the teams are not in this round on a different station
			if (stations.find(st => (st[round] !== undefined ? st[round] : []).indexOf(team) !== -1)) {
				continue;
			}
			
			let cur = (stations[station][round] || []);
			
			// we have max cap on the number of teams in given entry
			if (cur.length >= (three ? 3 : 2 )) {
				continue;
			}

			// check if we have already been with teams that area on this entry
			if (cur.find(cf => friends.indexOf(cf) !== -1) !== undefined) {
				continue;
			}

			// we need to clone structures, cause these might not be final solution
			let new_stations = _.cloneDeep(stations);
			let new_friends = _.cloneDeep(friends);
			let new_teams = _.cloneDeep(teams);
			let new_cur = _.cloneDeep(cur);
			
			Array.prototype.push.apply(new_friends, new_cur);
			new_cur.push(team);
			new_stations[station][round] = new_cur;
			new_teams[team].push(station);

			// try another assignment for the team - first for team of 2 and then team of 3
			let result = assign(team, new_stations, new_teams, new_friends);
			result = result || assign(team, new_stations, new_teams, new_friends, true);
			
			// we...