FF13-2 時の狭間 パズル解法検索スクリプト
Rev.3を表示中。最新版はこちら。
ファイナルファンタジー13-2の「時の狭間」の時計の文字盤(?)のようなものから数字を消していくパズルの、削除手順を探すスクリプト。
時の狭間 数字消しパズルの解法検索スクリプト
#!/usr/bin/perl use strict; use warnings; my $list = [{pos => 'A', val => 2}, {pos => 'B', val => 3}, {pos => 'C', val => 5}, {pos => 'D', val => 4}, {pos => 'E', val => 2}, {pos => 'F', val => 2}, {pos => 'G', val => 4}, {pos => 'H', val => 1}, {pos => 'I', val => 3}, {pos => 'J', val => 2}]; sub next_entry_idx { my ($list, $idx) = @_; my $ent = $list->[$idx]; my $diff = $ent->{val}; my $idx1 = $idx - $diff; if ($idx1 < 0) { $idx1 += @$list; } my $idx2 = $idx + $diff; if ($idx2 > @$list - 1) { $idx2 -= @$list; } if ($idx1 == $idx2) { return ($idx1); } else { return ($idx1, $idx2); } } sub is_removed { my ($stack, $idx) = @_; foreach my $i (@$stack) { return 1 if $i == $idx; } return 0; } sub remove_entry { my ($list, $removed, $idx) = @_; push @$removed, $idx; if (@$removed == @$list) { return 1; # 全部消せたので終了 } my @next = next_entry_idx($list, $idx); # 次の針の位置 foreach my $next_idx (@next) { next if is_removed($removed, $next_idx); # 針の先に数字がない if (remove_entry($list, $removed, $next_idx)) { return 1; # 解が見つかっている } # 次の手順を試す } # 手詰まり。一つもどる。 pop @$removed; return; } sub dump_result { my ($list, $removed) = @_; foreach my $idx (@$removed) { print "$list->[$idx]{pos} "; } print "\n"; } sub search { my ($list) = @_; my $removed = []; # 削除済みエントリ my $i; for ($i = 0 ; $i < @$list ; $i++) { if (remove_entry($list, $removed, $i)) { print "Found\n"; dump_result $list, $removed; return 1; } } return 0; } search $list;
スクリプトの$listに文字盤の数字の並びを設定する。例えば以下のような数字の並びになっている場合は、上記スクリプトのように$listを設定すればよい。A〜Jは位置を識別するためにつけた名前で、$listの'pos'に指定する。この例ではアルファベットにしているが、ひらがな等、別になんでもよい。設定する開始位置も12時位置でなくても構わない。
数字の並びの例
スクリプトを実行すると以下のように、数字を消す順番が表示される。
Found A I F D J B E C H G
A->I->F->..と順番に消していけばよい。
なかなか解けないのでスクリプトを作ったのだが、なんかいい解法があるのだろうか。