尝试为每支球队生成类似于2024/25欧洲冠军联赛瑞士系统格式的独特比赛配对

问题描述 投票:0回答:1

我正在尝试制作类似于新的欧洲冠军联赛格式的锦标赛配对。联赛阶段共有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 个匹配项。一些创建的比赛有未定义的对手。该代码确实没有考虑到无法为团队找到有效对手的情况。

你会如何制作一个回溯方法,以便它可以填补一些包含未定义对手的比赛?

javascript typescript algorithm
1个回答
0
投票

您可以暴力破解所有可能的球队组合,如果一支球队已经有 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]));
.

© www.soinside.com 2019 - 2024. All rights reserved.