python - 条件循环橄榄球抽签的列表操作

标签 python list algorithm round-robin sports-league-scheduling-problem

我学校的一位橄榄球教练要求我为即将到来的比赛编写一个有条件的橄榄球比赛抽签程序,任务安排如下:给定 1 - 12 队的名单,分为 3 组([Group1 = 1, 2, 3, 4], [Group2 = 5, 6, 7, 8,], [Group3 = 9, 10, 11, 12]) 使用以下条件生成并打印 11 循环赛:

  • Group1 中的团队不与 Group3 中的团队对抗
  • Group1 中的团队与 Group1 中的所有其他团队进行两次对抗(例如 1v2、2v1、1v3、3v1、1v4、4v1、1v5、5v1 ......)

    同样的规则适用于 Group3 中的团队,因为他们与 Group3 中的其他团队进行对抗

  • Group2 中的团队与其他所有团队进行一次比赛。
  • Group1 和 Group3 中的团队需要一个 Bye Game。

我尝试了很多次但不可避免地卡住了,以下是我的2次尝试:

尝试 1:

import operator
import functools
import random



###First Generation (Flawed unclean round robin)
def fixtures(teams):
    if len(teams) % 2:
        teams.append('Day off')  # if team number is odd - use 'day off' as fake team     

    rotation = list(teams)       # copy the list
    random.shuffle(rotation)

    fixtures = []
    for i in range(0, len(teams)-1):
        fixtures.append(rotation)
        rotation = [rotation[0]] + [rotation[-1]] + rotation[1:-1]

    return fixtures

def main():
    # demo code
    teams = ["Team1","Team2","Team3","Team4","Team5","Team6","Team7","Team8","Team9","Team10","Team11","Team12"]
    groupA = ["Team1","Team2","Team3","Team4"]
    groupB = ["Team5","Team6","Team7","Team8"]
    groupC = ["Team9","Team10","Team11","Team12"]

    # for one match each - use this block only
    matches = fixtures(teams)

    print("flawed matches:")
    RoundCounter = 0

    homeTeams = []
    awayTeams = []

    for f in matches:
        #print(f)
        homeTeams = f[::2]
        awayTeams = f[1::2]
        print("Home Teams:{}".format(homeTeams))
        print("Away Teams:{}".format(awayTeams))
        HomeTeamGroupA = set(homeTeams).intersection(groupA)
        HomeTeamGroupC = set(homeTeams).intersection(groupC)
        AwayTeamGroupA = set(awayTeams).intersection(groupA)
        AwayTeamGroupC = set(awayTeams).intersection(groupC)

        VSCounter = 0

        for p, o in zip(homeTeams, awayTeams):
            if p in HomeTeamGroupA:
                if o in AwayTeamGroupC:
                    AvsCPosition = awayTeams.index(o)
                    VSCounter += 1
                    RoundCleanUp(homeTeams, awayTeams, AvsCPosition, VSCounter) #if this is returned begin cleaning the round
                else: print("GroupA is versing either Group B or GroupA") #if this is returned it is a team 1-4 but is vs either group b or group a
            elif p in HomeTeamGroupC:
                if o in AwayTeamGroupA:
                    AvsCPosition = awayTeams.index(o)
                    VSCounter += 1
                    RoundCleanUp(homeTeams, awayTeams, AvsCPosition, VSCounter) #if this is returned begin cleaning the round
                else:
                    print("GroupC is versing either Group B or GroupC")  #if this is returned it is a team 9-12 but is vs either group b or group c
            else:
                pass

def RoundCleanUp(HTeam, ATeam, AvsCPos, VSCounter):
    ##gets Value of List at position
    HTeamVal = HTeam[AvsCPos]
    ATeamVal = ATeam[AvsCPos]
main()

尝试 2:

import operator
import functools
import random


def make_round(rotation, num_teams, fixtures):
    for i in range(num_teams - 1):
        rotation = list(range(1, num_teams + 1))
        # clip to 0 .. num_teams - 2 # if i == 0, no rotation is needed (and using -0 as list index will cause problems)
        i %= (num_teams - 1)
        if i:
            rotation = rotation[:1] + rotation[-i:] + rotation[1:-i]
        half = num_teams // 2
        fixtures.append(list(rotation[:half]))
        fixtures.append(list(rotation[half:][::-1]))
    return fixtures


def make_schedule(teams):
    """Produces RoundRobin"""
    # number of teams must be even
    TeamLength = len(teams)
    if TeamLength % 2:
        TeamLength += 1  # add a dummy team for padding

    # build first round-robin
    rotation = list(teams)
    Fixture = []
    schedule = make_round(rotation, TeamLength, Fixture)

    return schedule


def homeAwayRotation(matches):
    for homeTeams, awayTeams in zip(matches[0::2], matches[1::2]):
        print("Home Rotation: {}".format(homeTeams))
        print("Away Rotation: {}".format(awayTeams))
        validation(homeTeams, awayTeams)


def validation(homeTeams, awayTeams):
    groupA = [1, 2, 3, 4]
    groupC = [9, 10, 11, 12]


    for x, y in zip(homeTeams, awayTeams):
        if x in groupA:
            if y in groupC:
                AvsCPosition = awayTeams.index(y)
                cleanDirtyData(homeTeams, awayTeams, AvsCPosition)
            else:
                    # if this is returned it is a team 1-4 but is vs either group b or group a
                print("Group A vsing either itself or GroupB\n")
        elif x in groupC:
            if y in groupA:
                AvsCPosition = awayTeams.index(y)
                cleanDirtyData(homeTeams, awayTeams, AvsCPosition)
            else:
                # if this is returned it is a team 9-12 but is vs either group b or group c
                print("Group C vsing either itself or GroupB\n")
        else:
            # if this is returned it is a team in group B
            print("This is team B\n")


def cleanDirtyData(homeTeams, awayTeams, AvsCPosition):
    HTeamVal = homeTeams[AvsCPosition]
    ATeamVal = awayTeams[AvsCPosition]
    Dirtlist = []
    Dirtlist.append(HTeamVal)
    Dirtlist.append(ATeamVal)
def main():
    # demo code
    teams = ["Team1", "Team2", "Team3", "Team4", "Team5", "Team6",
             "Team7", "Team8", "Team9", "Team10", "Team11", "Team12"]

    # for one match each - use this block only
    matches = make_schedule(teams)

    print("flawed matches:")

    homeAwayRotation(matches)


main()

我的预期结果是打印每一轮,显示哪个团队正在对战哪个团队,每个团队都有这样的历史:

  • Group1 中的一个团队有一段历史:(以任何随机顺序排列)

    1v2、2v1、1v3、3v1、1v4、4v1、1v5、1v6、1v7、1v8,再见

  • Group2 中的一个团队有一段历史:(以任何随机顺序排列)

    5v1, 5v2, 5v3, 5v4, 5v6, 5v7, 5v8, 5v9 5v10, 5v11, 5v12

  • Group3 中的一个团队有一段历史:(以任意顺序排列)

    9v10、10v9、9v11、11v9、9v12、12v9、9v5、9v6、9v7、9v8,再见

我可能会做的任何指示或改进将不胜感激,因为我在过去的 2 周里一直被困在最后的障碍上

最佳答案

如果我理解的问题是正确的,那么你所需要的只是将团队与不同组中的每个成员进行一些组合。

我将一些代码放在一起应该可以解决您的问题:

def vs(team, group):
    matchups = map(lambda opponent: (team,opponent), group)
    matchups = filter(lambda tup: tup[0] != tup[1], matchups)
    return list(matchups)

def matches(teams):
    group_size = len(teams) // 3

    # Make the groups, basically just splitting the team list in three parts
    groups = [teams[:group_size], teams[group_size:2*group_size], teams[2*group_size:]]
    matchups = []
    for index, team in enumerate(teams):
        group_index = index // group_size
        current_matchup = []

        # Check if we're working with group 1 or 3
        if group_index == 0 or group_index == 2:

            # Flip the order of a tuple
            def flip(x):
                return (x[1], x[0])

            own_group = vs(team, groups[group_index])

            # Add matches against everyone in the group
            current_matchup.extend(own_group)

            # Add matches agains everyone in the group again, but now the current team is 'away'
            current_matchup.extend(list(map(flip, own_group)))

            # Add matches against everyone in group 2
            current_matchup.extend(vs(team, groups[1]))

            # Lastly, add the bye 
            current_matchup.append((team, "bye"))
        else:
            # Just all matches against all other teams, once.
            current_matchup.extend(vs(team, teams))
        matchups.append(current_matchup)
    return matchups

# This can be anything. Numbers, 'Team 1' or even 'The wondrous flying squirrels of death'
teams = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
# Make matches
matchups = matches(teams)


# Just pretty print
for i in range(len(matchups)):
    matches = '\n\t'.join(map(lambda m: f'{str(m[0]).rjust(10)} vs {str(m[1]).ljust(10)}', matchups[i]))
    print(f"Team '{teams[i]}' matches:\n\t{matches}")

关于python - 条件循环橄榄球抽签的列表操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57797966/

相关文章:

arrays - 确定数组是增加还是减少的最佳方法

c++ - 透视和双线性变换

python - 展平嵌套字典 - 将列表元素转换为字符串

python计算字符串列表中的单词数

python Pandas : Find a value in another dataframe and replace it

c - "temp=*q"和 "temp->link=*q"之间的区别

algorithm - 比较 Big O、Theta 和 Omega 之间的算法复杂度

python - tabula.exe 路径未在 pyqt5 中打开

list - 从 LISP 中带有子列表的列表中删除所有 nil

string - 如何在 Haskell 中通过列表理解正确生成字符串列表?