ping98k commited on
Commit
5831b86
·
1 Parent(s): 3d7317c

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +71 -33
main.py CHANGED
@@ -1,52 +1,90 @@
1
  import os
 
 
 
 
2
 
3
- TOP_K = int(os.getenv("TOP_K", 5))
 
 
4
 
5
- def play(a,b):
6
- return a
 
7
 
8
- def tournament(players):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  lost_to = {}
10
  current = players[:]
11
  while len(current) > 1:
12
- next_round = []
13
- for i in range(0, len(current) - 1, 2):
14
- a, b = current[i], current[i + 1]
15
- w = play(a, b)
16
- loser = b if w == a else a
17
  lost_to[loser] = w
18
- next_round.append(w)
19
  if len(current) % 2 == 1:
20
  next_round.append(current[-1])
21
  current = next_round
22
- champion = current[0]
23
- return champion, lost_to
24
 
25
  def get_candidates(champion, lost_to):
26
- c = {champion}
27
- for player, opponent in lost_to.items():
28
- if opponent == champion:
29
- c.add(player)
30
- return list(c)
31
 
32
- def playoff(candidates):
33
  wins = {p: 0 for p in candidates}
34
- for i in range(len(candidates)):
35
- for j in range(i + 1, len(candidates)):
36
- w = play(candidates[i], candidates[j])
37
- wins[w] += 1
 
 
 
38
  return sorted(candidates, key=lambda p: wins[p], reverse=True)
39
 
40
- def get_top(players, k=TOP_K):
41
- champion, lost_to = tournament(players)
42
- runnerup = lost_to.get(champion)
43
- finalists = [champion] + ([runnerup] if runnerup else [])
44
- semifinalists = [p for p, o in lost_to.items() if o in finalists and p not in finalists]
45
- candidates = set(finalists + semifinalists)
46
- candidates.update(get_candidates(champion, lost_to))
47
- ranking = playoff(list(candidates))
48
  return ranking[:k]
49
 
50
- players = [f"S{i}" for i in range(1, 21)]
51
- top_picks = get_top(players)
52
- print(top_picks)
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import random
3
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4
+ from tqdm import tqdm
5
+ import time
6
 
7
+ NUM_TOP_PICKS = int(os.getenv("NUM_TOP_PICKS", 5))
8
+ POOL_SIZE = int(os.getenv("POOL_SIZE", 20))
9
+ MAX_WORKERS = int(os.getenv("MAX_WORKERS", 10))
10
 
11
+ def score(player):
12
+ time.sleep(5)
13
+ return random.randint(1, 10)
14
 
15
+ def play(a, b):
16
+ time.sleep(5)
17
+ return a if score(a) >= score(b) else b
18
+
19
+ def precompute_scores(players, executor):
20
+ """Compute all scores in parallel once and return a dict."""
21
+ futures = {executor.submit(score, p): p for p in players}
22
+ scores = {}
23
+ for fut in tqdm(as_completed(futures), total=len(futures), desc="Scoring"):
24
+ p = futures[fut]
25
+ scores[p] = fut.result()
26
+ return scores
27
+
28
+ def tournament_round(pairs, executor):
29
+ """Play a batch of matches in parallel; returns list of (winner, loser)."""
30
+ futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
31
+ results = []
32
+ for fut in tqdm(as_completed(futures), total=len(futures),
33
+ desc="Tournament round", leave=False):
34
+ a, b = futures[fut]
35
+ w = fut.result()
36
+ loser = b if w == a else a
37
+ results.append((w, loser))
38
+ return results
39
+
40
+ def tournament(players, executor):
41
  lost_to = {}
42
  current = players[:]
43
  while len(current) > 1:
44
+ pairs = [(current[i], current[i+1]) for i in range(0, len(current)-1, 2)]
45
+ round_results = tournament_round(pairs, executor)
46
+ next_round = [w for w, _ in round_results]
47
+ for w, loser in round_results:
 
48
  lost_to[loser] = w
 
49
  if len(current) % 2 == 1:
50
  next_round.append(current[-1])
51
  current = next_round
52
+ return current[0], lost_to
 
53
 
54
  def get_candidates(champion, lost_to):
55
+ return [p for p, o in lost_to.items() if o == champion] + [champion]
 
 
 
 
56
 
57
+ def playoff(candidates, executor):
58
  wins = {p: 0 for p in candidates}
59
+ pairs = [(candidates[i], candidates[j])
60
+ for i in range(len(candidates)) for j in range(i+1, len(candidates))]
61
+ futures = {executor.submit(play, a, b): (a, b) for a, b in pairs}
62
+ for fut in tqdm(as_completed(futures), total=len(futures),
63
+ desc="Playoff", leave=False):
64
+ winner = fut.result()
65
+ wins[winner] += 1
66
  return sorted(candidates, key=lambda p: wins[p], reverse=True)
67
 
68
+ def get_top(players, executor, k=NUM_TOP_PICKS):
69
+ champion, lost_to = tournament(players, executor)
70
+ runnerup = lost_to.get(champion)
71
+ finalists = [champion] + ([runnerup] if runnerup else [])
72
+ semifinalists = [p for p, o in lost_to.items()
73
+ if o in finalists and p not in finalists]
74
+ candidates = set(finalists + semifinalists + get_candidates(champion, lost_to))
75
+ ranking = playoff(list(candidates), executor)
76
  return ranking[:k]
77
 
78
+ if __name__ == "__main__":
79
+ all_players = [f"S{i}" for i in range(1, 101)]
80
+ # reuse one executor for everything
81
+ with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
82
+ # 1) Precompute scores
83
+ scores = precompute_scores(all_players, executor)
84
+
85
+ # 2) Pick top N by score
86
+ top_n_players = sorted(all_players, key=lambda p: scores[p], reverse=True)[:POOL_SIZE]
87
+
88
+ # 3) Run tournament+playoff
89
+ top5 = get_top(top_n_players, executor)
90
+ print("🏆 Top picks:", top5)