将赛季时间表分成几周而不重复球队比赛
Breaking Season Schedule into Weeks Without Repeating Teams Playing
我正在努力制定联赛时间表,但我坚持认为在任何给定的一周内,一支球队应该只打一场比赛。
到目前为止,我已经确定了正确的比赛次数,并且每支球队与他们的分区对手比赛 4 次,与他们的跨分区对手比赛 2 次。这是我的代码:
let easternConfTeams = [a, b, c, d, e, f];
let westernConfTeams = [g, h, i, j, k, l];
const teamPool = [...easternConfTeams, ...westernConfTeams];
let schedule = teamPool.reduce((a, v, i) => {
for (let j = i + 1; j < teamPool.length; j++) {
if (i < 6) {
if (j < 6) {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
} else {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
}
} else {
if (j < 6) {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
} else {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
}
}
}
return a;
}, []);
然后我 运行 通过洗牌功能:
shuffle = (schedule) => {
let currentIndex = schedule.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = schedule[currentIndex];
schedule[currentIndex] = schedule[randomIndex];
schedule[randomIndex] = temporaryValue;
}
return schedule;
};
然而,我坚持最后一步,即将这个比赛时间表变成单独的几周。由于有 12 支球队,因此本赛季每周应该有 6 场比赛——在这六场比赛中,任何一支球队都不应出场两次。换句话说,每支球队每周都应该参加比赛,但只能参加一次。
一共192场,需要分成32周,每周6场。
我如何确保这一点?
这是一种基于 round robin tournament scheduling algorithm.
的替代方法
循环赛算法将生成一系列比赛轮次,其中每支球队在每一轮比赛中与其他球队比赛一次,而不会在任何一轮比赛中重复比赛。然后,有一个步骤根据需要重复这些回合并交替比赛(模拟主场/客场交替)。生成所有团队之间的比赛回合并重复两次。然后生成、组合并重复 in-conference 场比赛的回合(因为 in-conference 队在上一步中已经有 2 场比赛)。
结果是 32 轮(周),每轮 6 场比赛,每队在所有回合结束后与 non-conference 对手比赛两次,并与 in-conference 对手比赛 4 次。
const zip = (a, b) => a.map((e, i) => [e, b[i]]);
const combine = (a, b) => zip(a, b).map((e) => [...e[0], ...e[1]]);
const alternate = (rounds, repeats) => {
const alt = [];
for (let i = 0; i < repeats; i++) {
const next = i % 2 ? rounds.map((r) => r.map((m) => [m[1], m[0]])) : rounds;
alt.push(...next);
}
return alt;
};
const roundrobin = (teams) => {
const rounds = [];
const mid = teams.length / 2;
for (let i = 0; i < teams.length - 1; i++) {
const t = i ? [teams[0], ...teams.slice(-i), ...teams.slice(1, -i)] : teams;
const t1 = t.slice(0, mid);
const t2 = t.slice(mid).reverse();
rounds.push(zip(t1, t2));
}
return rounds;
};
const east = ['a','b','c','d','e','f'];
const west = ['g','h','i','j','k','l'];
const schedule = [
...alternate(roundrobin([...east, ...west]), 2),
...alternate(combine(roundrobin(east), roundrobin(west)), 2)
];
console.log(schedule);
我正在努力制定联赛时间表,但我坚持认为在任何给定的一周内,一支球队应该只打一场比赛。
到目前为止,我已经确定了正确的比赛次数,并且每支球队与他们的分区对手比赛 4 次,与他们的跨分区对手比赛 2 次。这是我的代码:
let easternConfTeams = [a, b, c, d, e, f];
let westernConfTeams = [g, h, i, j, k, l];
const teamPool = [...easternConfTeams, ...westernConfTeams];
let schedule = teamPool.reduce((a, v, i) => {
for (let j = i + 1; j < teamPool.length; j++) {
if (i < 6) {
if (j < 6) {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
} else {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
}
} else {
if (j < 6) {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
} else {
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
a.push(`${v} : ${teamPool[j]}`);
}
}
}
return a;
}, []);
然后我 运行 通过洗牌功能:
shuffle = (schedule) => {
let currentIndex = schedule.length,
temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = schedule[currentIndex];
schedule[currentIndex] = schedule[randomIndex];
schedule[randomIndex] = temporaryValue;
}
return schedule;
};
然而,我坚持最后一步,即将这个比赛时间表变成单独的几周。由于有 12 支球队,因此本赛季每周应该有 6 场比赛——在这六场比赛中,任何一支球队都不应出场两次。换句话说,每支球队每周都应该参加比赛,但只能参加一次。
一共192场,需要分成32周,每周6场。
我如何确保这一点?
这是一种基于 round robin tournament scheduling algorithm.
的替代方法循环赛算法将生成一系列比赛轮次,其中每支球队在每一轮比赛中与其他球队比赛一次,而不会在任何一轮比赛中重复比赛。然后,有一个步骤根据需要重复这些回合并交替比赛(模拟主场/客场交替)。生成所有团队之间的比赛回合并重复两次。然后生成、组合并重复 in-conference 场比赛的回合(因为 in-conference 队在上一步中已经有 2 场比赛)。
结果是 32 轮(周),每轮 6 场比赛,每队在所有回合结束后与 non-conference 对手比赛两次,并与 in-conference 对手比赛 4 次。
const zip = (a, b) => a.map((e, i) => [e, b[i]]);
const combine = (a, b) => zip(a, b).map((e) => [...e[0], ...e[1]]);
const alternate = (rounds, repeats) => {
const alt = [];
for (let i = 0; i < repeats; i++) {
const next = i % 2 ? rounds.map((r) => r.map((m) => [m[1], m[0]])) : rounds;
alt.push(...next);
}
return alt;
};
const roundrobin = (teams) => {
const rounds = [];
const mid = teams.length / 2;
for (let i = 0; i < teams.length - 1; i++) {
const t = i ? [teams[0], ...teams.slice(-i), ...teams.slice(1, -i)] : teams;
const t1 = t.slice(0, mid);
const t2 = t.slice(mid).reverse();
rounds.push(zip(t1, t2));
}
return rounds;
};
const east = ['a','b','c','d','e','f'];
const west = ['g','h','i','j','k','l'];
const schedule = [
...alternate(roundrobin([...east, ...west]), 2),
...alternate(combine(roundrobin(east), roundrobin(west)), 2)
];
console.log(schedule);