From a05a072dbfb444aeabd2821f4f1420272ddc676b Mon Sep 17 00:00:00 2001 From: jfvillablanca <31008330+jfvillablanca@users.noreply.github.com> Date: Tue, 7 Nov 2023 12:06:00 +0800 Subject: [PATCH] sol: lab6/world-cup --- lab6/world-cup/README.md | 1 + lab6/world-cup/answers.txt | 19 ++++++++++ lab6/world-cup/tournament.py | 70 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 lab6/world-cup/README.md create mode 100644 lab6/world-cup/answers.txt create mode 100644 lab6/world-cup/tournament.py diff --git a/lab6/world-cup/README.md b/lab6/world-cup/README.md new file mode 100644 index 0000000..0b75f6d --- /dev/null +++ b/lab6/world-cup/README.md @@ -0,0 +1 @@ +https://cs50.harvard.edu/x/2023/labs/6/ diff --git a/lab6/world-cup/answers.txt b/lab6/world-cup/answers.txt new file mode 100644 index 0000000..d3eede5 --- /dev/null +++ b/lab6/world-cup/answers.txt @@ -0,0 +1,19 @@ +Times: + +10 simulations: 0m0.027s +100 simulations: 0m0.028s +1000 simulations: 0m0.035s +10000 simulations: 0m0.156s +100000 simulations: 0m0.768s +1000000 simulations: 0m6.765s + +Questions: + +Which predictions, if any, proved incorrect as you increased the number of simulations?: + +With a small number of simulations, the probability of a country winning is not as correlated with the rating provided. + +Suppose you're charged a fee for each second of compute time your program uses. +After how many simulations would you call the predictions "good enough"?: + +I think, at around 10000 simulations, the rankings and winning percentages seem to have stabilized to based on historical data. It's fast enough that it runs in less than a second. diff --git a/lab6/world-cup/tournament.py b/lab6/world-cup/tournament.py new file mode 100644 index 0000000..e7a5927 --- /dev/null +++ b/lab6/world-cup/tournament.py @@ -0,0 +1,70 @@ +# Simulate a sports tournament + +import csv +import sys +import random + +# Number of simluations to run +N = 1000 + + +def main(): + # Ensure correct usage + if len(sys.argv) != 2: + sys.exit("Usage: python tournament.py FILENAME") + + teams = [] + # TODO: Read teams into memory from file + with open(sys.argv[1]) as file: + reader = csv.DictReader(file) + for team in reader: + team["rating"] = int(team["rating"]) + teams.append(team) + + counts = {} + # TODO: Simulate N tournaments and keep track of win counts + for i in range(N): + winner = simulate_tournament(teams) + if winner in counts: + counts[winner] += 1 + else: + counts[winner] = 1 + + # Print each team's chances of winning, according to simulation + # for team in sorted(counts, key=lambda team: counts[team], reverse=True): + # print(f"{team}: {counts[team] * 100 / N:.1f}% chance of winning") + + +def simulate_game(team1, team2): + """Simulate a game. Return True if team1 wins, False otherwise.""" + rating1 = team1["rating"] + rating2 = team2["rating"] + probability = 1 / (1 + 10 ** ((rating2 - rating1) / 600)) + return random.random() < probability + + +def simulate_round(teams): + """Simulate a round. Return a list of winning teams.""" + winners = [] + + # Simulate games for all pairs of teams + for i in range(0, len(teams), 2): + if simulate_game(teams[i], teams[i + 1]): + winners.append(teams[i]) + else: + winners.append(teams[i + 1]) + + return winners + + +def simulate_tournament(teams): + """Simulate a tournament. Return name of winning team.""" + # TODO + while len(teams) > 1: + teams = simulate_round(teams) + + return teams[0]["team"] + + +if __name__ == "__main__": + main()