I am trying to come up with an algorithm that checks all possible combinations in a list of players and makes two teams of 5 with the closest possible difference in total skillIndex
. So far I have come up with the following exhausting permutation:
I am wondering if there is a better way to come up with a result which would suggest the 5 best team combinations based on the skillIndex
. Do you guys have any idea what is an efficient way of solving this?
My end goal is to have two teams where one player can only be in one team. And the teams have a skillindex which is as close to each other as they can be.
My approach for now has been to find all possible combinations of the array, split this array in half so I have two teams. Then calculate the skillindex of both arrays and compare the difference between them. If the difference is <= 5 then print the generated team.
So one hard requirement is that with the same number of players teams consist of different players therefore I need multiple options.
const permutate = () => {
const presentPlayers = [
{ name: 'a', skillIndex: 100 },
{ name: 'b', skillIndex: 100 },
{ name: 'c', skillIndex: 90 },
{ name: 'd', skillIndex: 25 },
{ name: 'e', skillIndex: 60 },
{ name: 'f', skillIndex: 80 },
{ name: 'g', skillIndex: 70 },
{ name: 'h', skillIndex: 60 },
{ name: 'i', skillIndex: 50 },
{ name: 'j', skillIndex: 50 },
];
const getDifference = (a, b) => {
return Math.abs(a - b);
};
function permutation(array) {
function p(array, temp) {
let i;
let x;
if (!array.length) {
let team1Index = 0;
let team2Index = 0;
const half = temp.length / 2;
const team1 = temp.splice(0, half);
const team2 = temp.splice(-half);
team1.forEach((player) => {
team1Index += parseFloat(player.skillIndex, 10);
});
team2.forEach((player) => {
team2Index += parseFloat(player.skillIndex, 10);
});
const difference = getDifference(team1Index, team2Index);
if (difference === 5) {
console.log({ team1, team2 });
debugger;
}
result.push(temp);
}
for (i = 0; i < array.length; i++) {
x = array.splice(i, 1)[0];
p(array, temp.concat(x));
array.splice(i, 0, x);
}
}
const result = [];
p(array, []);
return result;
}
console.log(permutation(presentPlayers));
};
So for now I came up with this solution based mainly on the tips of you guys. I run this code 252 times:
for (let i = 0; i < presentPlayers.length; i++) {
const player = presentPlayers[i];
players.push(player);
}
for (let i = players.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * i);
const temp = players[i];
players[i] = players[j];
players[j] = temp;
}
let team1Index = 0;
let team2Index = 0;
const half = players.length / 2;
const team1 = players.splice(0, half);
const team2 = players.splice(-half);
team1.forEach((player) => {
team1Index += parseFloat(player.skillIndex, 10);
});
team2.forEach((player) => {
team2Index += parseFloat(player.skillIndex, 10);
});
const difference = getDifference(team1Index, team2Index);
const sortedTeam1 = team1.sort((a, b) => {
return b.skillIndex - a.skillIndex;
});
const sortedTeam2 = team2.sort((a, b) => {
return b.skillIndex - a.skillIndex;
});
if (difference < 10) {
proposedTeams.push({
sortedTeam1,
sortedTeam2,
difference,
team1Index,
team2Index,
goalSkill,
});
}