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

List manipulation for a Conditional Round-Robin Rugby Draw

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

我尝试了很多次,但不可避免地卡住了,以下是我的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()

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

我可能会做的任何指示或改进都将不胜感激,因为我在过去的 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}")