我有一个清单,如何创建不重复n次的伙伴



我无法想出解决方案,因此我想寻求帮助。我有一份名单:

var listNames = ['John', 'William', 'James', 'George', 'Charles',
'Frank', 'Joseph', 'Henry', 'Robert', 'Thomas',
'Edward', 'Harry', 'Walter', 'Arthur'];

我希望通过单击一个按钮在它们之间生成一些随机耦合,而不重复已经耦合的名称。示例:

John-James,William-George,Charles-Joseph,Frank-Henry,Robert-Edward,Thomas-Harry,Walter-Arthur

生成此列表后,我想生成其他列表n次,直到所有名称匹配在一起。我想做的一个例子是在这个网站上:https://www.blia.it/utili/campionato/。通过在列中添加名称,它可以生成团队配对的日历,并且不会重复同一配对超过2次。

如何在JavaScriptJava中执行此操作?感谢任何能帮助我的人。

我不懂数学,但实验表明,只有4、8、16、32个团队等产生了可能的解决方案。

根据您的评论,此编辑允许连续进行主客场比赛。我没有具体尝试,但这种尝试似乎已经产生了一个相当公平的解决方案。

如果你在下半赛季复制解决方案,并更换每对搭档,每支球队将获得完全相同数量的主客场比赛。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Season {
private static final int NUMBER_OF_TEAMS = 8 /* 4, 8, 16, 32, 64... */;
private static class Day {
private int           index    = -1;
private List<Pairing> pairings = new ArrayList<>();
@Override
public String toString() {
return String.format("Day %2d: %s", index + 1, pairings);
}
}
private static class Pairing {
private int a;
private int b;
@Override
public String toString() {
return String.format("%2d-%2d", a + 1, b + 1);
}
}
public static void main(String[] args) throws Exception {
List<Integer> teams = IntStream.range(0, NUMBER_OF_TEAMS).mapToObj(i -> Integer.valueOf(i)).collect(Collectors.toList());
List<Pairing> pairings = createPairings(teams);
System.out.println("all pairings: " + pairings);
List<Day> days = createMatchDays(teams, pairings);
System.out.println();
System.out.println("match days first half of season (systematic):");
days.forEach(i -> System.out.println(i));
alternateHomeAndAwayGames(days);
}
private static List<Pairing> createPairings(List<Integer> teams) {
// "n choose 2", or C(n,2)
List<Pairing> pairings = new ArrayList<>();
for(int a = 0; a < teams.size(); a++) {
for(int b = a + 1; b < teams.size(); b++) {
Pairing pairing = new Pairing();
pairing.a = teams.get(a);
pairing.b = teams.get(b);
pairings.add(pairing);
}
}
return pairings;
}
private static List<Day> createMatchDays(List<Integer> teams, List<Pairing> pairings) {
int numberOfMatchDays = teams.size() - 1;
int pairingsPerMatchDay = teams.size() / 2;
List<Pairing> remainingPairings = new ArrayList<>(pairings);
List<Day> days = new ArrayList<>();
for(int dayIndex = 0; dayIndex < numberOfMatchDays; dayIndex++) {
Day day = new Day();
days.add(day);
day.index = dayIndex;
Set<Integer> teamsAlreadyPlaying = new HashSet<>();
for(int i = 0; i < pairingsPerMatchDay; i++) {
Pairing pairing = findPairing(remainingPairings, teamsAlreadyPlaying);
day.pairings.add(pairing);
}
}
return days;
}
private static Pairing findPairing(List<Pairing> remainingPairings, Set<Integer> teamsAlreadyPlaying) {
for(Pairing candidate : remainingPairings) {
if(!teamsAlreadyPlaying.contains(candidate.a) && !teamsAlreadyPlaying.contains(candidate.b)) {
teamsAlreadyPlaying.add(candidate.a);
teamsAlreadyPlaying.add(candidate.b);
remainingPairings.remove(candidate);
return candidate;
}
}
throw new IllegalStateException("failed to find pairing");
}
private static void alternateHomeAndAwayGames(List<Day> days) {
System.out.println();
System.out.println("trying to alternate home and away games as much as possible...");
int[] repeatHome = new int[NUMBER_OF_TEAMS];
int[] repeatAway = new int[NUMBER_OF_TEAMS];
for(int dayIndex = 1; dayIndex < days.size(); dayIndex++) {
Day prevDay = days.get(dayIndex - 1);
Day nextDay = days.get(dayIndex);
System.out.println("fitting day " + (dayIndex + 1));
// mark for each team if it played home or away during last day
boolean[] playedHome = new boolean[NUMBER_OF_TEAMS];
boolean[] playedAway = new boolean[NUMBER_OF_TEAMS];
for(Pairing pairing : prevDay.pairings) {
playedHome[pairing.a] = true;
playedAway[pairing.b] = true;
}
// try to switch pairings of candidate, so that no team has to play home or away twice in a row
for(int pairIndex = 0; pairIndex < nextDay.pairings.size(); pairIndex++) {
Pairing pairing = nextDay.pairings.get(pairIndex);
if(playedHome[pairing.a] && playedAway[pairing.b]) {
switchTeamsInPairing(pairing);
}
if(!playedHome[pairing.a] && !playedAway[pairing.b]) {
// ok
playedHome[pairing.a] = true;
playedAway[pairing.b] = true;
continue;
}
// first try a-b
if(pairing.a > pairing.b) {
switchTeamsInPairing(pairing);
}
if(playedHome[pairing.a]) {
repeatHome[pairing.a]++;
System.out.println(String.format("%s  Pair %2d repeat team %2d: home+ %s away  %s", nextDay, pairIndex + 1, pairing.a + 1,
repeatHome[pairing.a], repeatAway[pairing.a]));
continue;
}
if(playedAway[pairing.b]) {
repeatAway[pairing.b]++;
System.out.println(String.format("%s  Pair %2d repeat team %2d: home  %s away+ %s", nextDay, pairIndex + 1, pairing.b + 1,
repeatHome[pairing.b], repeatAway[pairing.b]));
continue;
}
// then try b-a
switchTeamsInPairing(pairing);
if(playedHome[pairing.a]) {
repeatHome[pairing.a]++;
System.out.println(String.format("%s  Pair %2d repeat team %2d: home+ %s away  %s", nextDay, pairIndex + 1, pairing.a + 1,
repeatHome[pairing.a], repeatAway[pairing.a]));
continue;
}
if(playedAway[pairing.b]) {
repeatAway[pairing.b]++;
System.out.println(String.format("%s  Pair %2d repeat team %2d: home  %s away+ %s", nextDay, pairIndex + 1, pairing.b + 1,
repeatHome[pairing.b], repeatAway[pairing.b]));
continue;
}
}
}
System.out.println();
System.out.println("match days first half of season (shuffled):");
days.forEach(i -> System.out.println(i));
// count home/away
int[] home = new int[NUMBER_OF_TEAMS];
int[] away = new int[NUMBER_OF_TEAMS];
for(Day day : days) {
for(Pairing pairing : day.pairings) {
home[pairing.a]++;
away[pairing.b]++;
}
}
System.out.println("statistics");
for(int i = 0; i < NUMBER_OF_TEAMS; i++) {
System.out.println(String.format("Team %2d:  home/away: %2d/%2d  home/away-repeats: %2d/%2d", i + 1, home[i], away[i], repeatHome[i],
repeatAway[i]));
}
}
private static void switchTeamsInPairing(Pairing pairing) {
int tmp = pairing.a;
pairing.a = pairing.b;
pairing.b = tmp;
}
}

8个团队的输出:

all pairings: [ 1- 2,  1- 3,  1- 4,  1- 5,  1- 6,  1- 7,  1- 8,  2- 3,  2- 4,  2- 5,  2- 6,  2- 7,  2- 8,  3- 4,  3- 5,  3- 6,  3- 7,  3- 8,  4- 5,  4- 6,  4- 7,  4- 8,  5- 6,  5- 7,  5- 8,  6- 7,  6- 8,  7- 8]
match days first half of season (systematic):
Day  1: [ 1- 2,  3- 4,  5- 6,  7- 8]
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]
Day  3: [ 1- 4,  2- 3,  5- 8,  6- 7]
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]
Day  5: [ 1- 6,  2- 5,  3- 8,  4- 7]
Day  6: [ 1- 7,  2- 8,  3- 5,  4- 6]
Day  7: [ 1- 8,  2- 7,  3- 6,  4- 5]
trying to alternate home and away games as much as possible...
fitting day 2
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]  Pair  1 repeat team  1: home+ 1 away  0
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]  Pair  2 repeat team  4: home  0 away+ 1
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]  Pair  3 repeat team  5: home+ 1 away  0
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]  Pair  4 repeat team  8: home  0 away+ 1
fitting day 3
fitting day 4
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]  Pair  1 repeat team  5: home  1 away+ 1
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]  Pair  2 repeat team  6: home  0 away+ 1
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]  Pair  3 repeat team  3: home+ 1 away  0
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]  Pair  4 repeat team  4: home+ 1 away  1
fitting day 5
fitting day 6
fitting day 7
match days first half of season (shuffled):
Day  1: [ 1- 2,  3- 4,  5- 6,  7- 8]
Day  2: [ 1- 3,  2- 4,  5- 7,  6- 8]
Day  3: [ 4- 1,  3- 2,  8- 5,  7- 6]
Day  4: [ 1- 5,  2- 6,  3- 7,  4- 8]
Day  5: [ 6- 1,  5- 2,  8- 3,  7- 4]
Day  6: [ 1- 7,  2- 8,  3- 5,  4- 6]
Day  7: [ 8- 1,  7- 2,  6- 3,  5- 4]
statistics
Team  1:  home/away:  4/ 3  home/away-repeats:  1/ 0
Team  2:  home/away:  3/ 4  home/away-repeats:  0/ 0
Team  3:  home/away:  4/ 3  home/away-repeats:  1/ 0
Team  4:  home/away:  3/ 4  home/away-repeats:  1/ 1
Team  5:  home/away:  4/ 3  home/away-repeats:  1/ 1
Team  6:  home/away:  3/ 4  home/away-repeats:  0/ 1
Team  7:  home/away:  4/ 3  home/away-repeats:  0/ 0
Team  8:  home/away:  3/ 4  home/away-repeats:  0/ 1

为了生成不重复的配对,可以使用随机索引并将元素从数组中弹出,这样它们就不会重复。

对于问题的第二部分,我会为每个配对创建一个带有密钥条目的对象,并在每次抽奖后检查密钥是否不存在。

这是这个问题的蓝图。https://codesandbox.io/s/heuristic-grothendieck-vkt6f?file=/src/index.js

相关内容

  • 没有找到相关文章

最新更新