友人から次のようなオーダーがありました。
- 草野球の試合日程を決めたい。
- 6チームの総当たりで同じ組み合わせを2回ずつ。全部で30試合。
- グラウンドは1面のみ。
- 同一チームは2試合連続はなし。
つぎのように決めたところうまくいきました。チーム数が増えてもOKです。
ABCDEFの6チームの二回ずつ総当りを考える。
基本的な決め方は次の通り。
・A対BとB対Aを別の試合(二試合)と考える。
・同じ試合はない。
・同じチームが二試合連続にならない。
Aから順に試合相手を決めていく。
Fの次はAとなりループする。
常に右側のチームから順に試合相手を決めていく。
A Bと対戦。A対B
B 二試合連続なのでスキップ。
C Dと対戦。C対D
D 二試合連続なのでスキップ。
E Fと対戦。E対F
F 二試合連続なのでスキップ。
A Bは実施済み。Cと対戦。A対C
B Cは二試合連続なのでスキップ。Dと対戦。B対D
C Dは二試合連続なのでスキップ。Eと対戦。C対E
D Eは二試合連続なのでスキップ。Fと対戦。D対F
E Fは二試合連続なのでスキップ。Aと対戦。E対A
F Aは二試合連続なのでスキップ。Bと対戦。F対B
A Bは実施済み。Cは実施済み。Dと対戦。A対D
B Cと対戦。B対C
C 二試合連続なのでスキップ。
D Eと対戦。D対E
E 二試合連続なのでスキップ。
F Aと対戦。F対A
以下同様。
とは言え面倒だし、間違えそうなのでPythonで。
最初はライブラリを使ったりしましたが結果的に不要でした。
最初のteamsを書き換えれば、チーム名そのものを入れても、チーム数を増やしても一覧を作成します。
games = []
ichi = 0
for i in range(1000):
ichi = i % len(teams)
games.append([])
for j in range(1, len(teams)):
ichi_next = (ichi + j)%len(teams)
if (i == 0) or ((not ichi in game_mae) and (not ichi_next in game_mae) and (not [ichi, ichi_next] in games)):
games[i] = [ichi, ichi_next]
game_mae = [ichi, ichi_next]
break
games = [game for game in games if len(game) > 0]
for i, g in enumerate(games):
hidari = teams[g[0]]
migi = teams[g[1]]
text = f"第{i + 1}試合 {hidari} 対 {migi}"
print(text)
実行結果
第1試合 A 対 B
第2試合 C 対 D
第3試合 E 対 F
第4試合 A 対 C
第5試合 B 対 D
第6試合 C 対 E
第7試合 D 対 F
第8試合 E 対 A
第9試合 F 対 B
第10試合 A 対 D
第11試合 B 対 C
第12試合 D 対 E
第13試合 F 対 A
第14試合 B 対 E
第15試合 C 対 F
第16試合 D 対 A
第17試合 E 対 B
第18試合 F 対 C
第19試合 A 対 E
第20試合 B 対 F
第21試合 C 対 A
第22試合 D 対 B
第23試合 E 対 C
第24試合 F 対 D
第25試合 B 対 A
第26試合 D 対 C
第27試合 F 対 E
第28試合 C 対 B
第29試合 E 対 D
第30試合 A 対 F
コメント