snippetjavascriptMinor
JavaScript function to create 2 soccer teams as even as possible, from a list of players
Viewed 0 times
soccerteamscreatejavascriptfunctionplayerslistpossibleevenfrom
Problem
? Given a list of players with their respective scores (how well does a player play soccer, from 1 to 5 points), return two teams that are as even as possible.
I've created this code, which is a first version, but I really would like to hear about ideas of how can I improve it.
If it's easier, you can pull the code from here.
I've created this code, which is a first version, but I really would like to hear about ideas of how can I improve it.
exports.TeamCreator = (function () {
this.players = [];
function setPlayers(players){
this.players = Object.assign([], players);
}
function createTeams() {
var input = this.players;
var teams = [],
i = 0,
scores = [],
max = input.length;
scores["A"]=0; scores["B"]=0;
teams["A"]=[]; teams["B"]=[];
input.sort(function(a, b){ return b.score - a.score;});
var nextPlayer;
var teamForNextPlayer;
for (i = 0; i counterB) { //B has less players than A
teamForNextPlayer = "B";
if(scoreB >= scoreA){
getWorst();
}else{
getBest();
}
}
else if(counterA = scoreB){
getWorst();
}else{
getBest();
}
}
else //Same amount of players
{
getBest();
teamForNextPlayer = (scoreA >= scoreB) ? "B" : "A";
}
}
return {
teamA: teams["A"],
teamB: teams["B"],
diff: Math.abs(scores["A"] - scores["B"]),
scoreA: scores["A"],
scoreB: scores["B"]
};
}
return {
setPlayers : setPlayers,
createTeams: createTeams
}
}());If it's easier, you can pull the code from here.
Solution
First I would make each team an object with a score and players rather than an object for scores and one for players:
Once you have sorted the players by score it might be simpler to pick them off the list two at a time and assign the one with the higher score to the lower scoring team:
One advantage is this always returns the more powerful team first.
This algorithm is not ideal in that it doesn't always choose the most balanced team, for example given players with scores of 8, 4, 3, 3, 1 and 1, Team A will have players 8, 3 and 1 (score of 12) while team b will have players with scores of 4, 3 and 1 (totaling 8). It might be more reasonable to balance them as Team A: 8, 1, 1 and Team B 4, 3, 3 so that both teams have a score of 10. The logic for that might be:
var teams = [ { name:'A'; score: 0, players:[] },
{ name:'B', score: 0, players:[] };Once you have sorted the players by score it might be simpler to pick them off the list two at a time and assign the one with the higher score to the lower scoring team:
// Note: slice is probably better than Object.assign
let input = this.players.slice();
assert(input.length % 2 == 0, 'Need an equal number of players');
while (input.length > 0) {
let [strongerTeam, weakerTeam] = teams;
let [strongerPlayer, weakerPlayer] = input.slice(0,2);
addPlayer(strongerTeam, weakerPlayer);
addPlayer(weakerTeam, strongerPlayer);
sortTeams(teams);
}
function addPlayer(team, player) {
team.players.push(player);
team.score += player.score;
}
// Sort highest scoring team first
function sortTeams(teams) {
teams.sort(function(a, b) { return b.score - a.score;});
}
return teams;One advantage is this always returns the more powerful team first.
This algorithm is not ideal in that it doesn't always choose the most balanced team, for example given players with scores of 8, 4, 3, 3, 1 and 1, Team A will have players 8, 3 and 1 (score of 12) while team b will have players with scores of 4, 3 and 1 (totaling 8). It might be more reasonable to balance them as Team A: 8, 1, 1 and Team B 4, 3, 3 so that both teams have a score of 10. The logic for that might be:
while (input.length > 0) {
let [strongerTeam, weakerTeam] = teams;
let nextPlayer = input.slice(0,1)[0];
addPlayer(weakerTeam, nextPlayer);
if (strongerTeam.length - weakerTeam.length == input.length) {
addPlayers(strongerTeam, input);
input = [];
}
sortTeams(teams);
}
function addPlayers(team, players) {
for (let player of players) {
addPlayer(team, player);
}
}Code Snippets
var teams = [ { name:'A'; score: 0, players:[] },
{ name:'B', score: 0, players:[] };// Note: slice is probably better than Object.assign
let input = this.players.slice();
assert(input.length % 2 == 0, 'Need an equal number of players');
while (input.length > 0) {
let [strongerTeam, weakerTeam] = teams;
let [strongerPlayer, weakerPlayer] = input.slice(0,2);
addPlayer(strongerTeam, weakerPlayer);
addPlayer(weakerTeam, strongerPlayer);
sortTeams(teams);
}
function addPlayer(team, player) {
team.players.push(player);
team.score += player.score;
}
// Sort highest scoring team first
function sortTeams(teams) {
teams.sort(function(a, b) { return b.score - a.score;});
}
return teams;while (input.length > 0) {
let [strongerTeam, weakerTeam] = teams;
let nextPlayer = input.slice(0,1)[0];
addPlayer(weakerTeam, nextPlayer);
if (strongerTeam.length - weakerTeam.length == input.length) {
addPlayers(strongerTeam, input);
input = [];
}
sortTeams(teams);
}
function addPlayers(team, players) {
for (let player of players) {
addPlayer(team, player);
}
}Context
StackExchange Code Review Q#155943, answer score: 2
Revisions (0)
No revisions yet.