3人対戦ゲームの試合数・対戦表 / 組み合わせ(数え上げ)問題を線形計画問題ソルバ GLPK を使って解く
2021/07/29 19:01
・3人で行うゲームがある数え上げ問題なのですが、この問題を整数計画問題として(もともと数え上げ問題だったものを整数計画問題に「擬態」して、それ用のソルバで解けるようにして) GLPK (Gnu Linear Programming Kit) を使って解いてみたので、これで正解なのか自信がありませんが(なんだか A+ の成績はいただけたけど、正解したとは限らないし・・・、コロナ禍のもと対面授業ではなかったので質問の機会がなかったのです)、私なりの解答を披露したいと思います。
・9人が参加する
・各プレイヤーは4回だけプレイできて、さらに他のすべてのプレイヤーとちょうど1回ずつプレイする
・このような条件をみたすゲームの個数(=試合数)は何通りあるか、対戦表は作れるか
#Yahoo!知恵袋 でも、同じ問題の答えを聞いている人がいました(こちら や こちら)。
#前者の回答例は、私の解答での m02,m12,m22,m23,m30,m46,m47,m51,m63,m66,m74,m76 パターンで、対戦表では No. 352 にあたります。
#似てるけどちょっと違う出題に、数学の部屋『3人ゲームのリーグ戦』の「問題1」があります。
途中、GLPK を何百回も繰り返して実行する箇所がありますので、そういうところは perl スクリプトで自動実行しています。
答案
まず、9人に1,2,3,・・・,9と番号を付ける。9人のうち3人でゲームをするから、その組み合わせは {}_9 \mathrm{C}_3 で、84通りある。
この組み合わせにも番号を付け、それぞれ m01, m02, ..., m84 と表す。
一覧は次の通り。
m01 | [1 x 2 x 3] | m29 | [2 x 3 x 4] | m57 | [3 x 5 x 8] | ||
---|---|---|---|---|---|---|---|
m02 | [1 x 2 x 4] | m30 | [2 x 3 x 5] | m58 | [3 x 5 x 9] | ||
m03 | [1 x 2 x 5] | m31 | [2 x 3 x 6] | m59 | [3 x 6 x 7] | ||
m04 | [1 x 2 x 6] | m32 | [2 x 3 x 7] | m60 | [3 x 6 x 8] | ||
m05 | [1 x 2 x 7] | m33 | [2 x 3 x 8] | m61 | [3 x 6 x 9] | ||
m06 | [1 x 2 x 8] | m34 | [2 x 3 x 9] | m62 | [3 x 7 x 8] | ||
m07 | [1 x 2 x 9] | m35 | [2 x 4 x 5] | m63 | [3 x 7 x 9] | ||
m08 | [1 x 3 x 4] | m36 | [2 x 4 x 6] | m64 | [3 x 8 x 9] | ||
m09 | [1 x 3 x 5] | m37 | [2 x 4 x 7] | m65 | [4 x 5 x 6] | ||
m10 | [1 x 3 x 6] | m38 | [2 x 4 x 8] | m66 | [4 x 5 x 7] | ||
m11 | [1 x 3 x 7] | m39 | [2 x 4 x 9] | m67 | [4 x 5 x 8] | ||
m12 | [1 x 3 x 8] | m40 | [2 x 5 x 6] | m68 | [4 x 5 x 9] | ||
m13 | [1 x 3 x 9] | m41 | [2 x 5 x 7] | m69 | [4 x 6 x 7] | ||
m14 | [1 x 4 x 5] | m42 | [2 x 5 x 8] | m70 | [4 x 6 x 8] | ||
m15 | [1 x 4 x 6] | m43 | [2 x 5 x 9] | m71 | [4 x 6 x 9] | ||
m16 | [1 x 4 x 7] | m44 | [2 x 6 x 7] | m72 | [4 x 7 x 8] | ||
m17 | [1 x 4 x 8] | m45 | [2 x 6 x 8] | m73 | [4 x 7 x 9] | ||
m18 | [1 x 4 x 9] | m46 | [2 x 6 x 9] | m74 | [4 x 8 x 9] | ||
m19 | [1 x 5 x 6] | m47 | [2 x 7 x 8] | m75 | [5 x 6 x 7] | ||
m20 | [1 x 5 x 7] | m48 | [2 x 7 x 9] | m76 | [5 x 6 x 8] | ||
m21 | [1 x 5 x 8] | m49 | [2 x 8 x 9] | m77 | [5 x 6 x 9] | ||
m22 | [1 x 5 x 9] | m50 | [3 x 4 x 5] | m78 | [5 x 7 x 8] | ||
m23 | [1 x 6 x 7] | m51 | [3 x 4 x 6] | m79 | [5 x 7 x 9] | ||
m24 | [1 x 6 x 8] | m52 | [3 x 4 x 7] | m80 | [5 x 8 x 9] | ||
m25 | [1 x 6 x 9] | m53 | [3 x 4 x 8] | m81 | [6 x 7 x 8] | ||
m26 | [1 x 7 x 8] | m54 | [3 x 4 x 9] | m82 | [6 x 7 x 9] | ||
m27 | [1 x 7 x 9] | m55 | [3 x 5 x 6] | m83 | [6 x 8 x 9] | ||
m28 | [1 x 8 x 9] | m56 | [3 x 5 x 7] | m84 | [7 x 8 x 9] |
このm01~m84を複数組み合わせて(ただし個々のゲームは0回ないし1回だけ行われる)、
条件1 各プレーヤーは4回だけプレイする
条件2 他のすべてのプレイヤーとちょうど1回ずつプレイする
の両条件を満たすゲームの組み合わせを考える。
仮に12ゲーム必要なのだとしても(各プレイヤーが4回ずつ、1回のゲームで1/3の人しかプレイできないので 4×3=12より)、
{}_8{}_4 \mathrm{C}_1{}_2 = 112,992,892,764,570
と百兆を超えるとても大きな数となり、手作業で考えるのはとうてい無理なので、コンピュータをつかう。
コンピュータを使っても総当たり法では組み合わせ爆発を起こすので、線形計画法ソルバを利用する。
GLPKに与えるモデルファイルは次の通り。
game3.mod.txt
var m01 binary; var m02 binary; var m03 binary; var m04 binary; var m05 binary; var m06 binary; var m07 binary; var m08 binary; var m09 binary; var m10 binary; var m11 binary; var m12 binary; var m13 binary; var m14 binary; var m15 binary; var m16 binary; var m17 binary; var m18 binary; var m19 binary; var m20 binary; var m21 binary; var m22 binary; var m23 binary; var m24 binary; var m25 binary; var m26 binary; var m27 binary; var m28 binary; var m29 binary; var m30 binary; var m31 binary; var m32 binary; var m33 binary; var m34 binary; var m35 binary; var m36 binary; var m37 binary; var m38 binary; var m39 binary; var m40 binary; var m41 binary; var m42 binary; var m43 binary; var m44 binary; var m45 binary; var m46 binary; var m47 binary; var m48 binary; var m49 binary; var m50 binary; var m51 binary; var m52 binary; var m53 binary; var m54 binary; var m55 binary; var m56 binary; var m57 binary; var m58 binary; var m59 binary; var m60 binary; var m61 binary; var m62 binary; var m63 binary; var m64 binary; var m65 binary; var m66 binary; var m67 binary; var m68 binary; var m69 binary; var m70 binary; var m71 binary; var m72 binary; var m73 binary; var m74 binary; var m75 binary; var m76 binary; var m77 binary; var m78 binary; var m79 binary; var m80 binary; var m81 binary; var m82 binary; var m83 binary; var m84 binary; minimize z: m01 + m02 + m03 + m04 + m05 + m06 + m07 + m08 + m09 + m10 + m11 + m12 + m13 + m14 + m15 + m16 + m17 + m18 + m19 + m20 + m21 + m22 + m23 + m24 + m25 + m26 + m27 + m28 + m29 + m30 + m31 + m32 + m33 + m34 + m35 + m36 + m37 + m38 + m39 + m40 + m41 + m42 + m43 + m44 + m45 + m46 + m47 + m48 + m49 + m50 + m51 + m52 + m53 + m54 + m55 + m56 + m57 + m58 + m59 + m60 + m61 + m62 + m63 + m64 + m65 + m66 + m67 + m68 + m69 + m70 + m71 + m72 + m73 + m74 + m75 + m76 + m77 + m78 + m79 + m80 + m81 + m82 + m83 + m84 ; s.t. st1: m01 + m02 + m03 + m04 + m05 + m06 + m07 + m08 + m09 + m10 + m11 + m12 + m13 + m14 + m15 + m16 + m17 + m18 + m19 + m20 + m21 + m22 + m23 + m24 + m25 + m26 + m27 + m28 = 4; s.t. st2: m01 + m02 + m03 + m04 + m05 + m06 + m07 + m29 + m30 + m31 + m32 + m33 + m34 + m35 + m36 + m37 + m38 + m39 + m40 + m41 + m42 + m43 + m44 + m45 + m46 + m47 + m48 + m49 = 4; s.t. st3: m01 + m08 + m09 + m10 + m11 + m12 + m13 + m29 + m30 + m31 + m32 + m33 + m34 + m50 + m51 + m52 + m53 + m54 + m55 + m56 + m57 + m58 + m59 + m60 + m61 + m62 + m63 + m64 = 4; s.t. st4: m02 + m08 + m14 + m15 + m16 + m17 + m18 + m29 + m35 + m36 + m37 + m38 + m39 + m50 + m51 + m52 + m53 + m54 + m65 + m66 + m67 + m68 + m69 + m70 + m71 + m72 + m73 + m74 = 4; s.t. st5: m03 + m09 + m14 + m19 + m20 + m21 + m22 + m30 + m35 + m40 + m41 + m42 + m43 + m50 + m55 + m56 + m57 + m58 + m65 + m66 + m67 + m68 + m75 + m76 + m77 + m78 + m79 + m80 = 4; s.t. st6: m04 + m10 + m15 + m19 + m23 + m24 + m25 + m31 + m36 + m40 + m44 + m45 + m46 + m51 + m55 + m59 + m60 + m61 + m65 + m69 + m70 + m71 + m75 + m76 + m77 + m81 + m82 + m83 = 4; s.t. st7: m05 + m11 + m16 + m20 + m23 + m26 + m27 + m32 + m37 + m41 + m44 + m47 + m48 + m52 + m56 + m59 + m62 + m63 + m66 + m69 + m72 + m73 + m75 + m78 + m79 + m81 + m82 + m84 = 4; s.t. st8: m06 + m12 + m17 + m21 + m24 + m26 + m28 + m33 + m38 + m42 + m45 + m47 + m49 + m53 + m57 + m60 + m62 + m64 + m67 + m70 + m72 + m74 + m76 + m78 + m80 + m81 + m83 + m84 = 4; s.t. st9: m07 + m13 + m18 + m22 + m25 + m27 + m28 + m34 + m39 + m43 + m46 + m48 + m49 + m54 + m58 + m61 + m63 + m64 + m68 + m71 + m73 + m74 + m77 + m79 + m80 + m82 + m83 + m84 = 4; s.t. st12: m01 + m02 + m03 + m04 + m05 + m06 + m07 = 1; s.t. st13: m01 + m08 + m09 + m10 + m11 + m12 + m13 = 1; s.t. st14: m02 + m08 + m14 + m15 + m16 + m17 + m18 = 1; s.t. st15: m03 + m09 + m14 + m19 + m20 + m21 + m22 = 1; s.t. st16: m04 + m10 + m15 + m19 + m23 + m24 + m25 = 1; s.t. st17: m05 + m11 + m16 + m20 + m23 + m26 + m27 = 1; s.t. st18: m06 + m12 + m17 + m21 + m24 + m26 + m28 = 1; s.t. st19: m07 + m13 + m18 + m22 + m25 + m27 + m28 = 1; s.t. st23: m01 + m29 + m30 + m31 + m32 + m33 + m34 = 1; s.t. st24: m02 + m29 + m35 + m36 + m37 + m38 + m39 = 1; s.t. st25: m03 + m30 + m35 + m40 + m41 + m42 + m43 = 1; s.t. st26: m04 + m31 + m36 + m40 + m44 + m45 + m46 = 1; s.t. st27: m05 + m32 + m37 + m41 + m44 + m47 + m48 = 1; s.t. st28: m06 + m33 + m38 + m42 + m45 + m47 + m49 = 1; s.t. st29: m07 + m34 + m39 + m43 + m46 + m48 + m49 = 1; s.t. st34: m08 + m29 + m50 + m51 + m52 + m53 + m54 = 1; s.t. st35: m09 + m30 + m50 + m55 + m56 + m57 + m58 = 1; s.t. st36: m10 + m31 + m51 + m55 + m59 + m60 + m61 = 1; s.t. st37: m11 + m32 + m52 + m56 + m59 + m62 + m63 = 1; s.t. st38: m12 + m33 + m53 + m57 + m60 + m62 + m64 = 1; s.t. st39: m13 + m34 + m54 + m58 + m61 + m63 + m64 = 1; s.t. st45: m14 + m35 + m50 + m65 + m66 + m67 + m68 = 1; s.t. st46: m15 + m36 + m51 + m65 + m69 + m70 + m71 = 1; s.t. st47: m16 + m37 + m52 + m66 + m69 + m72 + m73 = 1; s.t. st48: m17 + m38 + m53 + m67 + m70 + m72 + m74 = 1; s.t. st49: m18 + m39 + m54 + m68 + m71 + m73 + m74 = 1; s.t. st56: m19 + m40 + m55 + m65 + m75 + m76 + m77 = 1; s.t. st57: m20 + m41 + m56 + m66 + m75 + m78 + m79 = 1; s.t. st58: m21 + m42 + m57 + m67 + m76 + m78 + m80 = 1; s.t. st59: m22 + m43 + m58 + m68 + m77 + m79 + m80 = 1; s.t. st67: m23 + m44 + m59 + m69 + m75 + m81 + m82 = 1; s.t. st68: m24 + m45 + m60 + m70 + m76 + m81 + m83 = 1; s.t. st69: m25 + m46 + m61 + m71 + m77 + m82 + m83 = 1; s.t. st78: m26 + m47 + m62 + m72 + m78 + m81 + m84 = 1; s.t. st79: m27 + m48 + m63 + m73 + m79 + m82 + m84 = 1; s.t. st89: m28 + m49 + m64 + m74 + m80 + m83 + m84 = 1;変数 m?? が、それぞれのゲームが行われる回数(0または1回)を表している。例えば変数 m03 は m03 のゲーム(1と2と5との対戦)が行われた回数を示す。
minimize z: で、目的関数(ダミーの式 ; m01 ~ m84 の合計 ; 条件1・2を満たすために合計何ゲーム必要なのか)を最小化させる解を求めることを指示している。
#これは別に最大化でも何でもいいはず。条件1・2を考えると、目的関数の値は一種類しか取り得ない。
# →そもそも、この行は無くてもかまわないようです。
#しかしこの解き方のように、目的関数を最大化/最小化させる意図が無い問題は、じつは線形計画問題・整数計画問題にはあたらない(ただの連立方程式・不等式)のだろうか?
#最適化を目指しているのではなくて、副産物的に手に入る解を拾い集めていくというやり方。
st1~9 で各人がちょうど4回だけプレイする(条件1)こと、st12~89 で同じ人とはちょうど1度だけプレイすること(条件2)を制約している。
st?? の 十の位・一の位の数字でおのおのプレイヤーを表している。例えば st38 は 3と8が対戦するゲーム(m12, m33, m53, m57, m60, m62, m64)の回数の合計がちょうど1回であるように制約してある。
次のように実行する。
glpsol -m game3.mod.txt -o game3.out.txt実行結果 game3.out.txt の内容は次の通り。
Problem: first Rows: 46 Columns: 84 (84 integer, 84 binary) Non-zeros: 588 Status: INTEGER OPTIMAL Objective: z = 12 (MINimum) No. Row name Activity Lower bound Upper bound ------ ------------ ------------- ------------- ------------- 1 z 12 2 st1 4 4 = 3 st2 4 4 = 4 st3 4 4 = 5 st4 4 4 = 6 st5 4 4 = 7 st6 4 4 = 8 st7 4 4 = 9 st8 4 4 = 10 st9 4 4 = 11 st12 1 1 = 12 st13 1 1 = 13 st14 1 1 = 14 st15 1 1 = 15 st16 1 1 = 16 st17 1 1 = 17 st18 1 1 = 18 st19 1 1 = 19 st23 1 1 = 20 st24 1 1 = 21 st25 1 1 = 22 st26 1 1 = 23 st27 1 1 = 24 st28 1 1 = 25 st29 1 1 = 26 st34 1 1 = 27 st35 1 1 = 28 st36 1 1 = 29 st37 1 1 = 30 st38 1 1 = 31 st39 1 1 = 32 st45 1 1 = 33 st46 1 1 = 34 st47 1 1 = 35 st48 1 1 = 36 st49 1 1 = 37 st56 1 1 = 38 st57 1 1 = 39 st58 1 1 = 40 st59 1 1 = 41 st67 1 1 = 42 st68 1 1 = 43 st69 1 1 = 44 st78 1 1 = 45 st79 1 1 = 46 st89 1 1 = No. Column name Activity Lower bound Upper bound ------ ------------ ------------- ------------- ------------- 1 m01 * 0 0 1 2 m02 * 0 0 1 3 m03 * 0 0 1 4 m04 * 1 0 1 5 m05 * 0 0 1 6 m06 * 0 0 1 7 m07 * 0 0 1 8 m08 * 0 0 1 9 m09 * 0 0 1 10 m10 * 0 0 1 11 m11 * 0 0 1 12 m12 * 1 0 1 13 m13 * 0 0 1 14 m14 * 1 0 1 15 m15 * 0 0 1 16 m16 * 0 0 1 17 m17 * 0 0 1 18 m18 * 0 0 1 19 m19 * 0 0 1 20 m20 * 0 0 1 21 m21 * 0 0 1 22 m22 * 0 0 1 23 m23 * 0 0 1 24 m24 * 0 0 1 25 m25 * 0 0 1 26 m26 * 0 0 1 27 m27 * 1 0 1 28 m28 * 0 0 1 29 m29 * 0 0 1 30 m30 * 0 0 1 31 m31 * 0 0 1 32 m32 * 0 0 1 33 m33 * 0 0 1 34 m34 * 1 0 1 35 m35 * 0 0 1 36 m36 * 0 0 1 37 m37 * 0 0 1 38 m38 * 1 0 1 39 m39 * 0 0 1 40 m40 * 0 0 1 41 m41 * 1 0 1 42 m42 * 0 0 1 43 m43 * 0 0 1 44 m44 * 0 0 1 45 m45 * 0 0 1 46 m46 * 0 0 1 47 m47 * 0 0 1 48 m48 * 0 0 1 49 m49 * 0 0 1 50 m50 * 0 0 1 51 m51 * 0 0 1 52 m52 * 1 0 1 53 m53 * 0 0 1 54 m54 * 0 0 1 55 m55 * 1 0 1 56 m56 * 0 0 1 57 m57 * 0 0 1 58 m58 * 0 0 1 59 m59 * 0 0 1 60 m60 * 0 0 1 61 m61 * 0 0 1 62 m62 * 0 0 1 63 m63 * 0 0 1 64 m64 * 0 0 1 65 m65 * 0 0 1 66 m66 * 0 0 1 67 m67 * 0 0 1 68 m68 * 0 0 1 69 m69 * 0 0 1 70 m70 * 0 0 1 71 m71 * 1 0 1 72 m72 * 0 0 1 73 m73 * 0 0 1 74 m74 * 0 0 1 75 m75 * 0 0 1 76 m76 * 0 0 1 77 m77 * 0 0 1 78 m78 * 0 0 1 79 m79 * 0 0 1 80 m80 * 1 0 1 81 m81 * 1 0 1 82 m82 * 0 0 1 83 m83 * 0 0 1 84 m84 * 0 0 1 Integer feasibility conditions: KKT.PE: max.abs.err = 0.00e+00 on row 0 max.rel.err = 0.00e+00 on row 0 High quality KKT.PB: max.abs.err = 0.00e+00 on row 0 max.rel.err = 0.00e+00 on row 0 High quality End of outputこれから、仮定の通り12ゲーム必要であり、その組み合わせは、
m04, m12, m14, m27, m34, m38, m41, m52, m55, m71, m80, m81であることがわかった(Activity が1となっている m?? の行を拾う)。
表1とつきあわせて対戦表にすると、
[ 1 x 2 x 6 ] [ 1 x 3 x 8 ] [ 1 x 4 x 5 ] [ 1 x 7 x 9 ] [ 2 x 3 x 9 ] [ 2 x 4 x 8 ]となる。
[ 2 x 5 x 7 ] [ 3 x 4 x 7 ] [ 3 x 5 x 6 ] [ 4 x 6 x 9 ] [ 5 x 8 x 9 ] [ 6 x 7 x 8 ]
組み合わせのパターンは複数あると思われるので、1度出たパターンは2度と現れないようにしてもう1度問題を解いてゆく。
具体的には、モデルファイルの末尾に
s.t. pm1: m04 + m12 + m14 + m27 + m34 + m38 + m41 + m52 + m55 + m71 + m80 + m81 <= 11;を追記して、解く。
この、得られた解が現れないようにする制約式を、追記をしてはまた解くということを、解が得られなくなるまで繰り返す。
具体的には、 sol.pl を実行して、エラーが出るまで待つ。
もし、最後までエラーを出さないようなら、for ループの上限の数字を大きくして再度実行する。
そうしたところ、840個の解が得られた後、新たな解を返さなくなった。
最終的に得られたモデルファイルは、次の通り。こちら→ joined.mod.txt
「s.t. pm840:~」まで生成されているのがわかる(最終行)。
問題の「ゲームの個数(=試合数)は何通りあるか」には少々文意がつかみかねるが、
「840通り」と答えた。
出来上がった joined.mod.txt から「s.t. pm???:~」行を拾い集めて、これだと各対戦が m?? 形式になっているので、
それを対戦表の形式に変換する(じっさいには中間ファイル prev_match_pattern.txt から make_match_table.pl を使って生成する)。
得られた対戦表は、こちら→ 対戦表.txt
ツール類
Perl で書いた各種自動化ツールはこんな感じです。Windows のコマンドライン上で動かしました。
sol.pl
use strict; unlink('prev_match_pattern.txt'); system('glpsol -m game3.mod.txt -o game3.out.txt'); for(my $i = 1; $i <= 1000; $i++){ print"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"; print "■■■■■ $i ■■■■■\n"; system('type game3.out.txt | perl pattern.pl >> prev_match_pattern.txt'); system('type prev_match_pattern.txt | perl make_st_prev_match_pattern.pl > st_prev_match.txt'); system('copy game3.mod.txt + st_prev_match.txt joined.mod.txt'); system('glpsol -m joined.mod.txt -o game3.out.txt'); }
pattern.pl
use strict; my @matches; foreach my $line (<>){ chomp($line); if($line =~ /(m\d\d)\s+\*\s+(\d)/){ push(@matches, $1) if($2 == 1); } } print join(',', @matches). "\n";
make_st_prev_match_pattern.pl
use strict; my $i = 1; foreach my $line (<>){ chomp $line; my @mts = split(/,/, $line); print "s.t. pm$i: ". join(' + ', @mts). " <= 11;\n"; $i++; }
制約式を生成するスクリプト st.pl (game3.mod.txt を用意するときに使う)
use strict; use warnings; use Math::Combinatorics; my @matches; push @matches, '0'; open(LIST, '9c3.txt'); foreach my $line(<LIST>){ chomp $line; push @matches, $line; } close(LIST); foreach my $player (1..9){ my @joined_match; print "s.t. st$player: "; foreach my $match (1..84){ if($matches[$match] =~ /$player/){ push @joined_match, sprintf('m%02d', $match); } } print join(' + ', @joined_match). " = 4;\n"; } print "\n"; my @combine = combine(2, 1..9); @combine = sort {$a->[0] <=> $b->[0]} @combine; foreach my $a_comb (@combine) { my @hit_match; my($p1, $p2) = @$a_comb; ($p1, $p2) = sort ($p1, $p2); print "s.t. st${p1}${p2}: "; foreach my $match (1..84){ if($matches[$match] =~ /$p1/ && $matches[$match] =~ /$p2/){ push @hit_match, sprintf('m%02d', $match); } } print join(' + ', @hit_match). " = 1;\n"; }
組み合わせ({}_9 \mathrm{C}_3)データファイル 9c3.txt
(1,2,3) (1,2,4) (1,2,5) (1,2,6) (1,2,7) (1,2,8) (1,2,9) (1,3,4) (1,3,5) (1,3,6) (1,3,7) (1,3,8) (1,3,9) (1,4,5) (1,4,6) (1,4,7) (1,4,8) (1,4,9) (1,5,6) (1,5,7) (1,5,8) (1,5,9) (1,6,7) (1,6,8) (1,6,9) (1,7,8) (1,7,9) (1,8,9) (2,3,4) (2,3,5) (2,3,6) (2,3,7) (2,3,8) (2,3,9) (2,4,5) (2,4,6) (2,4,7) (2,4,8) (2,4,9) (2,5,6) (2,5,7) (2,5,8) (2,5,9) (2,6,7) (2,6,8) (2,6,9) (2,7,8) (2,7,9) (2,8,9) (3,4,5) (3,4,6) (3,4,7) (3,4,8) (3,4,9) (3,5,6) (3,5,7) (3,5,8) (3,5,9) (3,6,7) (3,6,8) (3,6,9) (3,7,8) (3,7,9) (3,8,9) (4,5,6) (4,5,7) (4,5,8) (4,5,9) (4,6,7) (4,6,8) (4,6,9) (4,7,8) (4,7,9) (4,8,9) (5,6,7) (5,6,8) (5,6,9) (5,7,8) (5,7,9) (5,8,9) (6,7,8) (6,7,9) (6,8,9) (7,8,9)
対戦表出力スクリプト make_match_table.pl
use strict; my @a9c3; push(@a9c3, '0'); open(F9C3, '9c3.txt'); foreach my $line_9c3 (<F9C3>){ chomp $line_9c3; $line_9c3 =~ /(\d),(\d),(\d)/; push(@a9c3, [$1, $2, $3] ); } close(F9C3); my $i = 1; open(PMP, 'prev_match_pattern.txt'); foreach my $line_pmp (<PMP>){ chomp $line_pmp; print "■■■ 対戦表\ No. $i ■■■ ($line_pmp)\n"; my @ms = split(/,/, $line_pmp); my $j = 0; foreach my $a_match (@ms){ $j++; $a_match =~ /m(\d\d)/; my $m = int($1); print "[ ". $a9c3[$m]->[0]. ' x '. $a9c3[$m]->[1]. ' x '. $a9c3[$m]->[2]. " ] "; print "\n" if ($j % 6 == 0); } print "\n"; $i++; } close(PMP);
参考にしたもの
- SWA / KASAI Takaya さんによる 「最長片道きっぷの経路を求める」
- よねざわいずみさんによる動画 「よねざわいずみのFeel Fine TV!【#0302】JR最長O型きっぷを購入しました・そのルートの求め方大公開します【整数計画法】【LOP toolkit】」
- キューブ王さんによる 「GLPKでのペンシルパズル(ナンリンなど)攻略法」