WIN_POINTS = 1 DRAW_POINTS = 0 BYE_POINTS = 1 def calcRound(startList, endSet, thisEndList) : numLeft = sum(startList) if numLeft > 1: playUp = 0 for i in range(len(startList)-1,-1,-1) : if startList[i] > 0 : if playUp > i : #someone plays up startList[playUp] -= 1 startList[i] -= 1 # fork top seed wins upEndList = list(thisEndList) upEndList[playUp+WIN_POINTS] += 1 upEndList[i] += 1 calcRound(list(startList), endSet, upEndList) # fork top seed loses downEndList = list(thisEndList) downEndList[playUp] += 1 downEndList[i+WIN_POINTS] += 1 calcRound(list(startList), endSet, downEndList) return if startList[i] > 1 : half = startList[i] >> 1 #todo calculate intentional draws thisEndList[i+WIN_POINTS] += half thisEndList[i] += half startList[i] = startList[i] - half - half if startList[i] : # odd bracket, has to play down playUp = i numLeft = sum(startList) if numLeft == 1 : #almost done, odd one gets a bye for i in range(len(startList)) : if startList[i] : thisEndList[i+BYE_POINTS] += 1 startList[i] -= 1 break numLeft = sum(startList) if numLeft == 0 : #done endSet.add(tuple(thisEndList)) def highEndCount(resultSet, num) : count = [0, 1000] # safe "primer" numbers for e in resultSet : thisCount = sum(e[-num:]) count[0] = max(count[0], thisCount) count[1] = min(count[1], thisCount) return tuple(count) def rounds(players, cutSize) : before = set() calcRound([players], before) roundNum = 1 while 1 : cuts = highEndCount(before, WIN_POINTS*2) hopes = highEndCount(before, WIN_POINTS*3) if cuts[0] <= cutSize : return players, roundNum, cuts[0], cuts[1], hopes[0],hopes[1] roundNum += 1 after = set() for e in before : calcRound(list(e), after, [0]*(roundNum+1)) before = after import sys for e in range(4, int(sys.argv[1])) : print rounds(e, int(sys.argv[2]))