※この記事は,ルネサンス以前に書かれた記事です.ルネサンス後に通用する場合は十分ご注意ください※
次回表のチェックツールができました.
まだ次回表の正式な規格もできていないのになぁ,です.
で,現在使用中の次回表をチェックしてみてエラー無しを確認できました.
開発者向けなので,細かいごとはごちゃごちゃ書きません.perlの入手方法とか起動方法とか,優れた解説サイトで入手して下さい.
なので,要点だけ.
- 中学生の読書感想文並みのコードですので,権利なんて主張しません.移植でも書き換えでも自由にやって下さい.
- 次回表は,nexthand.txtというファイル名でお願いします.
個人的には,固定ファイル名じゃなくてパイプから入力する方が好きですが,実行環境は間違いなくWindowsなんで,DOS窓でシェルラッパが書けるわけでもないですから,パイプ使ってもイマイチだろうというところです. - 次回表のパターンのルールは,ヒットアンドブローの汎用形式である「正解の数・間違いの数」の二ケタとします.
Holithy☆さんがこれまで公開してくれた結果表や次回表はそのままでは使えません.次郎が必要なものを変換してどこかで公開します.
処理の内容を大雑把に説明しますと,
- 正解を一つ仮定して,次回表に従って手を進める.次回表に次の手が載っていなくなったら処理終了.
- その時点で正解に到達していればOK.達していなければNG.
- NGだったらパターンと仮定した正解を出力
- 仮定する正解を「1111」~「4444」の256通全部で,上の処理を行う.
- 最後にNGが一つもなかったら,NGなしのメッセージを出力.
5については少しだけ考える余地があります.つまり,「言うべきものがないなら黙っていろ」(カーニハンがそんなこと言ってました)の原則に引っかかるからです.でも,
- ポストプロセスは考えられない
- 処理が一瞬で終わる
という事情で,「問題なし」という主張をしたって構わないのではないか,ということです.瞬時に処理が終わって無反応だと,ちゃんと仕事したのかどうか不安になりますからね.まあ,これもご自由に書き換えてください.
マッチ関数は見ての通りで特に難しいことはありません.ただし,一度カウントしたものを何回もカウントしないように,カウント済みのものをマークする必要があります.今の仕様では「1234」の数字を使っていますから,それ以外の数字にしました.桁が変わらなければアルファベットでも記号でも何でも構いません.
ただし,正解側($ans)とお試し配置側($nh)で別な文字にしないと「重複カウント防止」の用を足しません.コードでは正解の方も書き換えてますが,よくよく考えると,お試し配置の方は書き換える必要がなかったですね.気になるなら削除して下さい.プログラムの実行時間がその分だけ短くなります.とはいえ,1/1,000秒単位の話だとは思いますが.
最後に,前回マッチ関数をマッハ関数と書き間違えてしまいました.誰が見ても分かり易い間違いなので混乱はなかったと思います.が,ちょっと恥ずかしい間違いでした.でもこれがバッハ関数と間違えたのなら,訳わからんだったでしょうけど.
my %nexthand, @ans; # 次回表の読み込み open(IN,"< nexthand.txt") or die "$!"; while (my $line = <IN>) { chomp($line); my ($pat,$hand) = split(/,/,$line,2); $pat =~ s/-//g; $nexthand{$pat}=$hand; } close(IN); # 全解答の作成 for ($i=1;$i<5;$i++) { for ($j=1;$j<5;$j++) { for ($k=1;$k<5;$k++) { for ($l=1;$l<5;$l++) { push(@ans,"$i$j$k$l"); } } } } # メインルーチン foreach ( @ans ) { $pat='p'; while($nexthand{$pat}) { $pat = $pat . &much($pat,$_); } if (substr($pat,-2,2) ne '40' ) { print "$pat,$_ ... failure\n"; $err_cnt++; } } # 結果出力 ($err_cnt > 0) or print "no error\n"; exit; sub much() { #パターンから配置を取得し,解と比較してヒントを得る. my ($pat,$ans) = @_; my $hit=0, $brrow=0, $nh=$nexthand{$pat}; for (0..3) { if (substr($ans,$_,1) eq substr($nh,$_,1)) { $hit++; # ブローで重複カウントしないように,ヒットでカウントしたものは # 無関係の文字に置き換えておく substr($ans,$_,1,'8'); substr($nh,$_,1,'9'); } } for ($i=0;$i<4;$i++) { for ($j=0;$j<4;$j++) { if (substr($ans,$i,1) eq substr($nh,$j,1)) { $brrow++; # 重複カウントしないように # 無関係な文字に置き換えておく substr($nh,$j,1,'9'); last; } } } return "$hit$brrow"; }