Lab6 : ワールドカップ
この Lab では1~2人のクラスメートと協力することは問題ありませんが、そのグループのすべての受講生が等しく実習に貢献することが求められます。
FIFAワールドカップのシミュレーションプログラムを作成します。
$ python tournament.py 2018m.csv
Belgium: 20.9% chance of winning
Brazil: 20.3% chance of winning
Portugal: 14.5% chance of winning
Spain: 13.6% chance of winning
Switzerland: 10.5% chance of winning
Argentina: 6.5% chance of winning
England: 3.7% chance of winning
France: 3.3% chance of winning
Denmark: 2.2% chance of winning
Croatia: 2.0% chance of winning
Colombia: 1.8% chance of winning
Sweden: 0.5% chance of winning
Uruguay: 0.1% chance of winning
Mexico: 0.1% chance of winning
〆切
2021年12月31日金曜日11:59 PM (東部標準時) までに提出してください。
背景
サッカーのワールドカップ (W杯) の決勝トーナメントは16チームで行われます。各ラウンドでは、それぞれのチームが別のチームと対戦し、負けたチームは除外されます。2チームしか残っていない場合、決勝戦の勝者がチャンピオンとなります。
サッカーでは、各チームの相対的な技術レベルを表す数値であるFIFA レーティングが与えられます。FIFAの格付が高いほど、過去の試合の結果が良いことを示しており、2チームのFIFAの格付を考慮すると、どちらかのチームが現在の格付けに基づいて試合に勝つ確率を推定することが可能です。前回のワールドカップ直前のFIFAランクは、2018年5月の男子FIFAランクと2019年3月の女子FIFAランクです。
この情報をもとに、1チームで終わるまでのラウンドシミュレーションを繰り返すことで、大会全体をシミュレーションすることができます。また、どのチームがトーナメントで優勝する可能性が高いかを推測するには、トーナメントを何度もシミュレートし (例:1000シミュレーション)、各チームがシミュレートしたトーナメントで何回優勝したかをカウントします。
この実習での課題は、Pythonを使用してこれを行うことです。
始め方
- GitHubアカウントを使用してide.cs50.ioにログインします。
- ターミナルウィンドウで
wget https://cdn.cs50.net/2020/fall/labs/6/lab6.zip
を実行し、ラボの配布コードのZipファイルをダウンロードします。 - ターミナルウィンドウで
unzip lab6.zip
を実行し、そのZipファイルを解凍します。 - ターミナルウィンドウで、
cd lab6
を実行してディレクトリをlab6
ディレクトリに変更します。
理解を深める
まず、2018m.csv
ファイルを確認します。このファイルには、2018年男子ワールドカップのノックアウトラウンドの16チームと各チームの評価が含まれています。CSVファイルには2つの列があり、1つはチーム (チームの国名を表す) 、もう1つはレーティング (チームのレーティングを表す) です。
各ラウンドでどのチームが互いに対戦するかは、チームがリストされる順序によって決まります(例えば、第一ラウンドで、ウルグアイはポルトガルと対戦し、フランスはアルゼンチンと対戦します。次のラウンドで、ウルグアイ-ポルトガルの試合の勝者は、フランス-アルゼンチンの試合の勝者と対戦します)。したがって、このファイルに表示されるチームの順序は編集しないでください。
最終的にPythonでは、「チーム」と「格付」という2つの値を含む辞書として各チームを表すことができます。例えばウルグアイの場合、Pythonでは{"team": "Uruguay", "rating": 976}
と表現したいでしょう。
次に、2019w.csv
を見てみましょう。このファイルには、同じ形式で2019年女子ワールドカップのデータが含まれています。
tournament.py
を開いて、既にコードがいくらか書かれていることを確認してください。上にある変数N
は、実行するワールドカップシミュレーションの数を表します。この場合は1000です。
simulate_game
関数は、2つのチームを入力として受け取り (各チームがチーム名とチームの格付を含む辞書であることを思い出してください) 、それらのチーム間のゲームをシミュレートします。最初のチームが勝つと、関数はTrue
を返します。それ以外の場合はFalse
を返します。
simulate_round
関数は、チームのリスト (teams
という変数) を入力として受け取り、チームの各ペア間のゲームをシミュレートします。次に、この関数は、そのラウンドに勝ったすべてのチームのリストを返します。
main
関数では、まずlen(sys.argv)
(コマンドライン引数の数) が2であることを確認します。コマンドライン引数を使用して、トーナメントシミュレーションの実行に使用するチームCSVファイルをPythonに指示します。次に、teams
(最終的にはチームのリストとなります) と呼ばれるリストと、counts
(チーム名とそのチームがシミュレーションされたトーナメントで優勝した回数を関連付ける) と呼ばれる辞書を定義します。現時点ではどちらも空なので、どのように完成させるかはあなた次第です。
最後に、main
の最後に、シミュレーションで何回優勝したか (counts
によって) の高い順にチームを並べ、それぞれのチームがワールドカップで優勝する確率をプリントします。
teams
とcounts
を定義し、simulate_tournament
関数を作成するのが今回の課題です。
実装の詳細
複数のトーナメントをシミュレートし、各チームの勝率を出力するように、tournament.py
の実装を完了します。
まずmain
で、CSVファイルからプログラムのメモリにチームデータを読み込み、各チームをリストteams
に追加します。
- 使用するファイルは、コマンドライン引数として指定されます。ファイルの名前にアクセスするには、
sys.argv[1]
を使用します。 open(filename)
を使用してファイルを開くことができます。ここで、filename
はファイルの名前を格納する変数です。- ファイル
f
を取得したら、csv.DictReader(f)
を使用して 「リーダー」 を作成できます。リーダーとは、Pythonでループしてファイルを1行ずつ読み取り、各行を辞書として扱うオブジェクトです。 - デフォルトでは、ファイルから読み込まれるすべての値は文字列になります。そのため、まずチームの
rating
をint
に変換してください (Pythonでint
関数を使用してこれを行うことができます) 。 - 最終的には、各チームの辞書を
teams
に追加します。関数呼び出しteams.append(x)
は、リストteams
にx
を追加します。 - 各チームは、チーム名
team
と格付rating
を含む辞書でなければならないことを思い出してください。
次に、simulate_tournament
関数を実装します。この関数は、チームのリストを入力として受け入れ、1つのチームが残るまでラウンドを繰り返しシミュレートします。この関数は、そのチームの名前を返します。
simulate_round
関数を呼び出すことができます。simulate_round
関数は、単一のラウンドをシミュレートし、チームのリストを入力として受け入れ、すべての勝者のリストを返します。x
がリストの場合、len(x)
を使用してリストの長さを決定できます。- トーナメントのチーム数を想定するのではなく、2の累乗を想定してもいいでしょう。
最後にmain
関数に戻り、N
回トーナメントのシミュレーションを実行し、各チームが辞書counts
で何回優勝したかを追跡します。
- たとえば、ウルグアイが2トーナメントで優勝し、ポルトガルが3トーナメントで優勝したとすると、カウント辞書
counts
は{"Uruguay": 2, "Portugal": 3}
になります。 simulate_tournament
を使用して各トーナメントをシミュレートし、勝者を決定します。counts
が辞書である場合、counts[team_name] = x
のような構文は、team_name
に格納されたキーをx
に格納された値に関連付けることを思い出してください。- Pythonで
in
キーワードを使用すると、その辞書にすでに特定のキーがあるかどうかをチェックできます。例えば、if "Portugal" in counts:
は、「Portugal
」が既に辞書counts
に存在する値を持っているかどうかを調べます。
ウォークスルー
ヒント
- ファイルを読み込むときは、
filename
をファイル名、file
を変数として、この構文を使用すると便利です。
withopen(filename)
as
file: reader=csv.DictReader(file)
- Pythonでリストの最後に追加するには、
.append()
関数を使用します。
テスト
プログラムは、次の例に従って動作する必要があります。シミュレーションはそれぞれランダムであるため、出力は以下の例と完全には一致しません。
$ python tournament.py 2018m.csv
Belgium: 20.9% chance of winning
Brazil: 20.3% chance of winning
Portugal: 14.5% chance of winning
Spain: 13.6% chance of winning
Switzerland: 10.5% chance of winning
Argentina: 6.5% chance of winning
England: 3.7% chance of winning
France: 3.3% chance of winning
Denmark: 2.2% chance of winning
Croatia: 2.0% chance of winning
Colombia: 1.8% chance of winning
Sweden: 0.5% chance of winning
Uruguay: 0.1% chance of winning
Mexico: 0.1% chance of winning
$ python tournament.py 2019w.csv
Germany: 17.1% chance of winning
United States: 14.8% chance of winning
England: 14.0% chance of winning
France: 9.2% chance of winning
Canada: 8.5% chance of winning
Japan: 7.1% chance of winning
Australia: 6.8% chance of winning
Netherlands: 5.4% chance of winning
Sweden: 3.9% chance of winning
Italy: 3.0% chance of winning
Norway: 2.9% chance of winning
Brazil: 2.9% chance of winning
Spain: 2.2% chance of winning
China PR: 2.1% chance of winning
Nigeria: 0.1% chance of winning
- 2018年と2019年のワールドカップで実際に何が起こったのか不思議に思うかもしれません。男子ではフランスが決勝でクロアチアに勝ちました。ベルギーはイギリスを破って3位になりました。女子ではアメリカが決勝でオランダに勝ちました。イングランドはスウェーデンが破って3位に入りました。
解決方法がわかりませんか?
コードのテスト方法
check50
を使用して以下を実行し、コードの正確さを評価してください。ただし、コンパイルとテストは必ず自分で行ってください。
check50 cs50/labs/2021/x/worldcup
以下を実行し、style50
を使用してコードのスタイルを評価します。
style50 tournament.py
提出方法
次のコマンドを実行し、GitHubのユーザー名とパスワードを入力してログインします。セキュリティのため、パスワードには実際の文字ではなくアスタリスク (*
) が表示されます。
submit50 cs50/labs/2021/x/worldcup