| Bytes | Lang | Time | Link |
|---|---|---|---|
| nan | def run_tournamentcontestants | 241205T032736Z | Eonema |
| nan | 241203T133842Z | Spitemas | |
| 003 | Python | 241129T040850Z | tsh |
| nan | 241129T152337Z | Themooni | |
| nan | 241129T114407Z | Themooni |
def run_tournament(contestants, games, play_game):
winners = contestants[0:len(contestants)]
upnext = winners
# run several elimination rounds
while True:
# temp list of winners
winners = []
seconds = []
# run games
while len(upnext) > 0:
games -= 1
# choose size of game:
if len(upnext) < 4:
# all that are left
n = len(upnext)
elif len(upnext) % 4 > 0:
# play games of 3 until it's divisible by 4
n = 3
else:
n = 4
upnow = upnext[0:n]
del upnext[0:n]
# play game
results = play_game(upnow)
# record winner
winners.append(results[0])
seconds.append(results[1])
# winners go in next round
upnext = winners
# if 4 or fewer winners, go to next stage
if len(winners) <= 4:
break
# second stage: repeated games with finalists:
finalists = winners + seconds[:(4-len(winners))]
scores = { nm : 0 for nm in finalists }
while games > 0:
games -= 1
results = play_game(finalists)
for i in range(len(results)):
scores[list(results)[i]] += 3-i
# return winner
return max(scores, key=scores.get)
Here's my best attempt:
import random
def run_tournament(contestants, games, play_game):
contestants = [[x, 0, 0] for x in contestants]
min_games_played = 0
remove_per_round = min((len(contestants) - 4) / min(games - 2, games * 0.9), 3)
to_remove = 0
while games > 0:
games -= 1
options = [x for x in contestants if x[1] == min_games_played]
if len(options) > 4:
random.shuffle(options)
options = options[:4]
elif len(options) < 4:
min_games_played += 1
random.shuffle(contestants)
options = options + [x for x in contestants if x[1] == min_games_played and x[0] not in options][:4 - len(options)]
result = play_game([x[0] for x in options])
for option in options:
option[1] += 1
option[2] += result.index(option[0])
to_remove += remove_per_round
while to_remove >= 0.99 and len(contestants) > 4:
to_remove -= 1
worst_score = max([x[2]/x[1] for x in contestants if x[1] > 0])
for contestant in contestants:
if contestant[1] == 0:
continue
if contestant[2] / contestant[1] == worst_score:
contestants.remove(contestant)
break
best_score = min([x[2]/x[1] for x in contestants if x[1] > 0])
for contestant in contestants:
if contestant[2] / contestant[1] == best_score:
return contestant[0]
```
Python 3
A, B, C, D, E = 10000.0, 100.0, 1.003, 50.0, 0.95
def choose_player(players):
name, score, win, lose = players
return (lose, -win)
def record_result(win, lose):
win[2] += 1
lose[3] += 1
p = 1 - 1 / (1 + C ** (lose[1] - win[1]))
win[1] += p * B * E ** (win[2] + win[3])
lose[1] -= p * B * E ** (lose[2] + lose[3])
def run_tournament(contestants, games, play_game):
map = {c: [c, A, 0, 0] for c in contestants}
scores = [map[c] for c in contestants]
for i in range(games):
players = sorted(scores, key=choose_player)[:4]
names = [p[0] for p in players]
result = play_game(names)
for index, win in enumerate(result):
for lose in result[:index:-1]:
record_result(map[win], map[lose])
final = sorted(scores, key=lambda s: -s[1])
return final[0][0]
Bash
This is, short of always returning contestants[0], the worst algorithm possible. takes the first 4 contestants, runs a game with them. returns the winner of that game. use with helper.
read numcont
contestants=()
for i in $(seq 1 $numcont); do
read cont
contestants+=("$cont")
done
read numgames
echo "run"
echo 4
for i in $(seq 0 3); do
echo "${contestants[$i]}"
done
results=()
for i in $(seq 0 3); do
read res
results+=("$res")
done
echo "ret"
echo "${results[0]}"
Ten weak players : 14684 0.63590
Two groups : 19462 0.78026
Huge pool : 6031 0.78219
32 skilled players : 8392 0.73068
Average : 12142 0.73226
Other language helper
put the following code in a file named helper.py:
from subprocess import Popen, PIPE
import sys
from time import sleep
sleeptime = 0
def run_tournament(contestants, games, play_game):
# contestants: an array of contestant names
# games: a number - this is the maximum number of games you're allowed to play
# play_game: a function which takes an array of contestants and returns the outcome of a game which they all play
# returns a single string, expected to be the name of one of the competitors
process = Popen([arg for arg in sys.argv[2:]], stdout=PIPE, stdin=PIPE, text=True, universal_newlines=True, bufsize=1)
process.stdin.write(str(len(contestants)) + "\n")
for c in contestants:
process.stdin.write(c + "\n")
process.stdin.write(str(games) + "\n")
i=0
while i<games:
#sleep(sleeptime)
line = process.stdout.readline().strip()
if line == "run":
#sleep(sleeptime)
numplayers = int(process.stdout.readline())
players = []
for j in range(numplayers):
#sleep(sleeptime)
players.append(process.stdout.readline().strip())
res = play_game(players)
for p in res:
process.stdin.write(p+"\n")
i+=1
elif line == "ret":
#sleep(sleeptime)
return process.stdout.readline().strip()
else:
raise ChildProcessError("Command not in [run, ret] recieved")
raise ChildProcessError("No games are left, but never returned")
run using python3 main.py helper $(which <program>) [additional args passed to program...]
From the perspective of your program, the protocol looks like:
STDIN STDOUT
init phase:
<number of contestants>
<name of contestant 1>
... repeat n times
<number of games>
->goto loop
loop phase:
run
->goto "run"
(or)
ret
->goto "ret"
"run" phase:
<number of contestants in that game>
<name of contestant 1>
...repeat n times
<name of winner>
...additional contestants, sorted
->goto loop
"ret" phase:
<name of overall winner>
program is expected to terminate here.
Notes:
- If you exceed the max number of games, an exception will be raised and no points will be awarded
- If you output something not in [run,ret] during the loop phase, an exception will be raised and no points will be awarded
- This is considerably slower than equivalent python implementations. a very basic bash implementation only runs at 240 it/s on my computer, taking 7 minutes to finish a run.
- If you find the code hanging, it's probably because the python wrapper is too fast for your program. Set
sleeptimeto a low value like0.0005and uncomment all thesleep()calls. This will make it run even slower, but sometimes you need it to run at all.