ptrvch
@ptrvch
вебдев-энтузиаст. Django, AngularJS

Как реализовать расписание кругового турнира?

Существует ли изящный способ реализации алгоритма, на вход которого подается массив участников и номер тура, на выходе - в определенном порядке сформированные пары соперников.
Принцип построения расписания описан здесь, а выглядит так:
Первый тур:
home: [t0 t1 t2 t3 t4 ]
guest: [t5 t6 t7 t8 t9 ]
Второй тур:
home: [t0 t5 t1 t2 t3]
guest: [t6 t7 t8 t9 t4]
третий тур:
home: [t0 t6 t5 t1 t2]
guest: [t7 t8 t9 t4 t3]


Возможно, существут готовые решения по другому алгоритму, но я не в состоянии составить релевантный запрос в гугле.
  • Вопрос задан
  • 2029 просмотров
Решения вопроса 2
@Mercury13
Программист на «си с крестами» и не только
Других методов я просто не вижу. Искать «round-robin tournament algorithm». Но, по-моему, проще поворачивать не кольцо, а схему матчей, поставив одну из команд (лучше последнюю) в центр круга.
https://commons.wikimedia.org/wiki/File:Round-robi...
Round-robin-schedule-span-diagram.svg
Матчам 2-13, 3-12 и т.д. даём фиксированные направления, причём попеременно: 2-13, 12-3, 11-4…
Направление матча 1-14 постоянно меняется.

Если команды нумеруются от 0 до N−1, N — чётное, алгоритм получается такой.
trans := случайная перестановка чисел 0 … N−1

если N чётное
  то M := N−1
  иначе M := N

цикл 2half = false…true
  цикл round = 0…M−1
    цикл shift = 1…[M/2]
      home := (round + shift) % M
      away := (round + M − shift) % M
      если (shift нечётное) xor 2half
        обменять home, away
      вывести trans[home], trans[away]

    если N чётное
      home := round
      away := M
      если (round нечётное) xor 2half
        обменять home, away
      вывести trans[home], trans[away]

Для чётного N одна команда постоянно меняет поле, у остальных — единожды на круге сбивается. Для нечётного N ничего не сбивается.
Ответ написан
ptrvch
@ptrvch Автор вопроса
вебдев-энтузиаст. Django, AngularJS
По запросу 'Round-robin tournament algorithm' нашел всё-таки образец, который смог транслировать в JS. Вот моя реализация только для четного количества команд (для нечетного предлагается добавить в массив фантомного участника):
// На входе - массив с командами и опционально - необходимый тур
function schedule(array, round) { // если тур не указан - создаётся всё расписание целиком
    if (!round) {
        var teams = array.length,
            // точка, после которой команды будут меняться местами "дома - гость"
            halfTour = (teams - 1),
            totalRounds = halfTour * 2,
            matchesPerRound = teams / 2,
            matches = [],
            rounds = [],
            round,
            match,
            home,
            away,
            swap,
            currentRoundText;
        for (round = 0; round < totalRounds; round++) {
            currentRoundText = [(round + 1)];
            matches = [];
            for (match = 0; match < matchesPerRound; match++) {
                home = (round + match) % (teams - 1);
                away = (teams - 1 - match + round) % (teams - 1);
                if (match === 0) {
                    away = teams - 1;
                }
                if (round >= halfTour) { 
                    swap = home;
                    home = away;
                    away = swap;
                }
                currentRoundText += ('[' + array[home]+ ' ' + array[away] + ']');
                matches.push([array[home], array[away]]);
            }
            console.log(currentRoundText);
            rounds.push(matches);
        }
        return rounds;
    }
    // Если раунд указан, просчитывается весь турнир и берется нужный элемент массива
    return schedule(array)[round - 1]; 
}
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
trurl123
@trurl123
Очень понятно как реализовывать описано тут chess.sainfo.ru/tabl/tablei.html
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы