- 「2連鎖」の状態を100種類以上,書いてください.
(略)
ぷよぷよ2連鎖100種類 - わさっき
- 最初(1連鎖目)はちょうど4個消え,2連鎖目もちょうど4個消えます.
- 消える4個+4個以外のぷよ(おじゃまぷよを含む)は使用しません.
- フィールドは6列です(7列を使う連鎖は,認めません).
- 鏡像は同一とします.
- 組み方や発火点が違っていても,消去を始める状態が同じなら,同一とします.
- 1組のぷよを置いて,消去を始めるという状態に限定します.
- 1連鎖目のぷよは「1」,2連鎖目のぷよは「2」で表記します.
- プログラムで生成するのではなく,手で(テキストエディタで)一つ一つ書きます.
プログラムで生成してみました.いつもならRubyのソースを出して,解説してから,実行結果としていますが,今回は規模が大きいので見送ります.それでも少しは解説を.
フィールドを2次元配列で保持した上で,消去判定(4個以上くっついているかの判定)や消去・落下処理は,過去にCで書いたり授業にしたりしているので,Rubyでも問題なく作成できました.
その連鎖シュミレータを足がかりに,「1」を4個と「2」を4個,ランダムに並べて,最初に「1」,次に「2」が消える2連鎖になり,かつ発火点を持つ(どこか1組のぷよを取り除けば,消去が起こらない状態になっている)ものを検査するコードも,書けました.
あとは全組み合わせを生成すれば,それぞれを上記の検査コードに通して,OKになるものを解として出力するわけです.生成方法は,手書きのときと同じで,『最下段が何になるかで場合分けしてから,それぞれでパターンを漏れなくダブりなく,書いていきました』.
具体例を.本日は,ぷよの文字を半角で表現しています.
2 2 2 11 112
このフィールド状態を,「112, :1222:1」で表します.カンマの前の112は,最下段を左から右に並べたもの,:1222:1はコロン区切りで,列ごとに,下から上にどの文字を置くかを指示したものです.この例では以下のようになります.
- 最初の:の左には何もないので,左端最下段の1の上には,何も積まれません.
- 最初の:の右は1222となっているので,左から2列目は,最下段の1の上に,1,2,2,2と積みます.
- 2番目の:の右は2となっているので,左から3列目は,最下段の2の上に,2を積みます.
生成方法は後回しにして,鏡像チェックについて書いておきます.2種類行います.まず最下段のチェックです.これは最下段文字列,上の例なら「112」と,それを反転した「211」とを比較して,もとのほうが小さいか等しければ採用,大きければ棄却します.
次に,最下段文字列とその反転したものが等しい,すなわち最下段でぷよが左右対称に配置している場合には,それより上の置き方でも,鏡像チェックが必要となります.別の例を出しますと…
2 1 1 11 222
これは「222, 1:1112:」という表現になります.「1:1112:」を,コロン単位(文字単位ではなく)で反転すると,「:1112:1」となります.これは以下のように,もとのと左右対称なフィールドを意味します.
2 1 1 11 222
ということで,コロン区切りの文字列(この例だと「1:1112:」)と,それをコロン単位で反転させたもの(同「:1112:1」)を文字列比較して,候補のほうが小さいか等しければ採用,大きければ棄却しました.
生成については,4個+4個に限定しないことにしました.任意の文字列を入力にとります.内部では,1文字単位に分割*1してから,最下段に置く個数(列数),具体的には1から6までのそれぞれについて,その個数だけ順に抽出します.鏡像チェックを通れば,残りの各文字と,列数マイナス1個の「:」について,順列を作ります.文字列化して,最下段が対称形ならここでも鏡像チェックを行います.これが通れば(もしくは最下段が対称でないか,1列しかないときには,2度目の鏡像チェックを行うことなく),2連鎖かどうか検査すべきフィールドの完成です.
ここで,最下段の「順に抽出」と,2段目移行の「順列」は,重複に注意した順列となります.自作するより,既存のものを探しました.[ruby-list:37550]順列イテレータのArray#perm2が,希望するものなので,使用しました.Ruby 1.9でも問題なく動作しました.
それともう一つ,フィールドに置くべきぷよの文字のリスト(4個+4個なら,1,1,1,1,2,2,2,2)から,最下段の文字を取り除く処理が必要なことに気づきました.Array#- は,配列の要素を集合と見なして,集合差を求めるもののようで,irbで確認すると
$ irb irb(main):001:0> [1,1,1,1,2,2,2,2]-[2,2,2] => [1, 1, 1, 1] irb(main):002:0> [1,1,1,1,2,2,2,2]-[1,1,2] => []
となります.メソッドを定義してもよかったのですが,http://f52.aaa.livedoor.jp/~maraigue/multiset/を利用しました.
実行結果です.4個+4個の全パターンについては,前回との比較のため,すべて載せます.
No.1 2 1 1 1 1 2 2 2 No.2 2 2 2 1 12 11 No.3 2 1 12 12 12 No.4 2 2 2 1 11 12 No.5 2 2 12 11 12 No.6 2 2 11 12 12 No.7 22 12 11 12 No.8 22 11 12 12 No.9 2 2 12 11 12 No.10 2 2 11 12 12 No.11 2 2 21 11 12 No.12 22 21 11 12 No.13 2 2 21 11 12 No.14 2 2 2 1 11 12 No.15 2 1 1 1 12 22 No.16 2 2 1 1 11 22 No.17 2 1 12 11 22 No.18 2 1 11 12 22 No.19 12 12 11 22 No.20 12 11 12 22 No.21 2 2 11 11 22 No.22 22 11 11 22 No.23 21 11 12 22 No.24 2 1 11 12 22 No.25 2 1 1 1 1 2 22 No.26 2 2 2 12 111 No.27 2 2 122 111 No.28 2 2 122 111 No.29 22 212 111 No.30 2 2 2 21 111 No.31 2 2 212 111 No.32 2 2 1 12 112 No.33 2 12 12 112 No.34 2 1 122 112 No.35 2 12 12 112 No.36 2 22 11 112 No.37 2 22 11 112 No.38 22 112 112 No.39 2 2 2 11 112 No.40 2 2 112 112 No.41 2 21 21 112 No.42 22 211 112 No.43 2 2 1 21 112 No.44 2 1 212 112 No.45 2 2 211 112 No.46 22 211 112 No.47 2 2 2 1 1 112 No.48 2 2 1 12 112 No.49 2 12 12 112 No.50 2 2 2 11 112 No.51 2 22 11 112 No.52 2 22 11 112 No.53 2 2 2 11 112 No.54 2 1 1 12 122 No.55 2 1 1 1 2 122 No.56 2 2 1 11 122 No.57 2 12 11 122 No.58 2 1 112 122 No.59 2 11 12 122 No.60 2 12 11 122 No.61 12 112 122 No.62 2 11 12 122 No.63 2 21 11 122 No.64 2 2 111 122 No.65 2 21 11 122 No.66 21 112 122 No.67 22 111 122 No.68 2 2 111 122 No.69 2 2 1 11 122 No.70 2 1 112 122 No.71 2 2 111 122 No.72 22 111 122 No.73 2 2 111 122 No.74 2 12 11 212 No.75 2 12 11 212 No.76 12 112 212 No.77 2 21 11 212 No.78 22 111 212 No.79 2 2 1 11 212 No.80 2 1 112 212 No.81 2 2 111 212 No.82 2 11 21 212 No.83 2 1 1 21 212 No.84 2 1 1 1 1 222 No.85 2 1 1 11 222 No.86 1 12 11 222 No.87 2 11 11 222 No.88 2 1 111 222 No.89 2 11 11 222 No.90 12 111 222 No.91 1 2 111 222 No.92 1 21 11 222 No.93 21 111 222 No.94 2 1 1 11 222 No.95 2 1 111 222 No.96 2 1 1 1 1 222 No.97 2 122 1112 No.98 2 122 1112 No.99 2 122 1112 No.100 2 2 1 2 1112 No.101 2 212 1112 No.102 2 221 1112 No.103 2 2 12 1112 No.104 22 12 1112 No.105 2 122 1112 No.106 2 2 12 1112 No.107 22 21 1112 No.108 2 2 21 1112 No.109 2 212 1112 No.110 2 2 2 1 1112 No.111 2 2 12 1112 No.112 2 1 12 1122 No.113 12 12 1122 No.114 1 12 2 1122 No.115 22 11 1122 No.116 2 2 11 1122 No.117 2 112 1122 No.118 2 11 2 1122 No.119 2 1 21 1122 No.120 2 211 1122 No.121 2 2 1 1 1122 No.122 2 1 12 1122 No.123 2 1 1 2 1122 No.124 2 2 11 1122 No.125 22 11 1122 No.126 2 112 1122 No.127 2 2 11 1122 No.128 2 112 1122 No.129 2 1 1 1 1222 No.130 2 1 11 1222 No.131 12 11 1222 No.132 21 11 1222 No.133 2 111 1222 No.134 2 1 11 1222 No.135 2 111 1222 No.136 2 111 1222 No.137 2 112 2112 No.138 2 1 12 2112 No.139 22 11 2112 No.140 12 11 2122 No.141 2 1 11 2122 No.142 2 111 2122 No.143 2 1 1 1 2122 No.144 2 1 11 2122 No.145 21 11 2122 No.146 2 111 2122 No.147 222 11112 No.148 2 22 11112 No.149 2 22 11112 No.150 2 2 2 11112 No.151 122 11122 No.152 2 1 2 11122 No.153 1 2 2 11122 No.154 2 12 11122 No.155 2 12 11122 No.156 12 2 11122 No.157 2 21 11122 No.158 2 2 1 11122 No.159 2 12 11122 No.160 2 1 2 11122 No.161 1 12 11222 No.162 2 11 11222 No.163 2 1 1 11222 No.164 2 11 11222 No.165 2 11 11222 No.166 22 111122 No.167 2 2 111122 No.168 2 2 111122 No.169 1 2 111222 No.170 12 111222 No.171 2 1 111222
手書きの前回は138でしたので,30個ほど,漏れがあったということです.最下段が「111122」という消し方は,完全に見落としていました.
せっかく,4個+4個に限定しないことにしたのですから,別のも試しました.
1連鎖目に「1」がちょうど5個消え,2連鎖目も「2」がちょうど5個消えるパターンです.482種類ありました.最初と最後のほか,途中を100単位で抜き出しています.
No.1 22 11 12 12 12 No.100 2 2 11 112 212 No.200 22 2111 1122 No.300 22 1111 2122 No.400 2 2 111 11222 No.482 2 111 121222
4個+4個+4個の3連鎖も,試しました.8204通りと出ました.こちらは1000番単位で.
No.1 3 3 3 2 2 2 13 11 12 No.1000 2 2 23 13 112 133 No.2000 2 31 211 231 233 No.3000 2 2 323 132 1113 No.4000 1233 1122 1332 No.5000 3 2 11 31 21 2233 No.6000 23 33 312 11122 No.7000 3 2 2 2 1 11 21333 No.8000 233 111 212233 No.8204 3 2 1111 222333
解の数と作業量を,表にしました.
4個+4個 | 5個+5個 | 4個+4個+4個 | |
---|---|---|---|
解の数 | 171 | 482 | 8204 |
検査対象の数 | 4294 | 48426 | 17768208 |
実行時間 | 約5秒 | 約30秒 | 約2時間 |
*1:そういえば「分割する」を「バラす」と言わなくなったなあ….