我正在尝试制作类似于新的欧洲冠军联赛格式的锦标赛配对。联赛阶段共有36支球队参赛。他们被分成4个盆。每支球队将进行 8 场比赛(每组 2 名对手)。总共有 144 场比赛。我很难想出一个具有良好回溯逻辑的函数。这是我失败的代码:
https://jsfiddle.net/4cgm1Lo8/5/
const pots = [
["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"],
["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8","B9"],
["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8","C9"],
["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8","D9"],
];
const MATCH_COUNT = 144;
const MAX_ROUNDS = 8
function run() {
const teamIds = _.flatten(pots)
return teamIds.reduce((matches,thisTeamId) => {
for (let round = 0; round < MAX_ROUNDS; round++) {
const thisTeamMatches = matches.filter(match => match.includes(thisTeamId))
if (thisTeamMatches.length >= MAX_ROUNDS) {
break;
}
const pool = teamIds.filter(poolTeamId => {
const encounteredBefore = thisTeamMatches.find(match => match.includes(poolTeamId))
const potEncounterCount = thisTeamMatches.filter(match => {
const opponentId = match.find(m => m != thisTeamId)
return getTeamPot(opponentId, pots) === getTeamPot(poolTeamId, pots)
})
const poolTeamIdMatches = matches.filter(match => match.includes(poolTeamId))
return poolTeamId != thisTeamId && !encounteredBefore && potEncounterCount.length < 2 && poolTeamIdMatches.length < MAX_ROUNDS
})
matches.push([thisTeamId, _.sample(pool)])
}
return matches
}, [] as string[][])
}
function getTeamPot(teamId: string, pots: string[][]) {
return pots.findIndex((pot) =>
pot.find((potTeamId) => potTeamId === teamId),
);
}
function getOpponent(yourTeamId: string, match: string[][]){
return match.find(m => m != thisTeamId)
}
console.log(run())
此功能无法创建 144 个匹配项。一些创建的比赛有未定义的对手。该代码确实没有考虑到无法为团队找到有效对手的情况。
你会如何制作一个回溯方法,以便它可以填补一些包含未定义对手的比赛?
您可以暴力破解所有可能的球队组合,如果一支球队已经有 2 场比赛,则可以跳过。
但这可能会暴露出你的期望存在一些问题,因为并不是所有需要的球队都可以用于给定的球队,我猜有些球队应该比赛超过 8 次:
const pots = [
["A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8"],
["B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"],
["C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8"],
["D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8"],
];
const set = new Set, counts = {}, matches = [], potMatchCount = 2;
const push = (a, b) => {
if(a === b) return;
const key = [a,b].sort().join('');
const aKey = [a,b[0]].sort((a,b) => b.length-a.length).join('');
const bKey = [a[0],b].sort((a,b) => b.length-a.length).join('');
if((counts[aKey] ?? 0) < potMatchCount && (counts[bKey] ?? 0) < potMatchCount){
if(set.has(key)) return;
set.add(key);
matches.push([a,b]);
counts[aKey] = (counts[aKey] ?? 0) + 1;
counts[bKey] = (counts[bKey] ?? 0) + 1;
}
}
for(const a of pots.flat()){
for(const b of pots.flat()){
push(a,b);
}
}
console.log('total matches:', matches.length);
//console.log(JSON.stringify(matches));
const grouped = pots.flat().map(team => [team, matches.filter(arr => arr.includes(team)).map(arr => arr.filter(t => t !== team)[0])]);
grouped.forEach(team => console.log(team[0], ':', ...team[1]));
.