巨大Hit and Blow
#Hit and Blow use List::Util(shuffle); ($max_kind, $max_length) = (26, 70); ($kind, $length, $seed) = @ARGV; unless($kind){ print <<"EOM"; Hit and Blow 答えの文字を推理する遊びです。答えだと思う文字列を入力してください。 使い方: スクリプト名 文字の種類数 文字長 問題番号 文字の種類数に正の数を指定すると、答えが文字重複なしになります。 文字の種類数に負の数を指定すると、答えが文字重複ありになります。 文字の種類数、文字長、問題番号が同一なら、答えは同一になりますので じっくり解きたい場合に向いています。 ただしperlのseed関数とList::Utilモジュールに依存していますので それらに変更があった場合、答えも変更される可能性があります。 EOM } srand $seed; if($kind < 0){ #文字種 $kind = $max_kind < -$kind ? -$max_kind : $kind; $length = $length < $max_length ? $length : $max_length; @answer = map{(A..Z)[rand -$kind]}1..$length; print "mode:文字重複あり\n"; }else{ $kind = $max_kind < $kind ? $max_kind : $kind; $length = $length < $kind ? $length : $kind; @answer = A..Z; @answer = shuffle @answer[0..$kind-1]; @answer = @answer[0..$length-1]; print "mode:文字重複なし\n"; } #print "答え".(join'',@answer)."\n"; print "文字種 ".(join '',map{[A..Z]->[$_]}(0..-1+abs $kind))."\n"; while(1){ $count++; my($hit, $blow, %input_blow, %answer_blow)=(0,0); print '!>'.(join' ',(map{'****'}(1..(int $length/4))),("*" x ($length % 4))); print "\n?>"; $input = <STDIN>; $input =~ tr/a-z \t\n/A-Z/d; @input = split //, $input; for$i(0..$#answer){ if($input[$i] eq $answer[$i]){ $hit++; }else{ $input_blow{$input[$i]}++; $answer_blow{$answer[$i]}++; } } last if $hit == $length; $blow = grep{exists $answer_blow{$_}} keys %input_blow; print "$count回目:位置も種類も合っている文字数(hit) $hit / 種類だけ合っている文字数(blow) $blow\n\n"; } print "\n正解。 答えは 「".(join'', @answer)."」です。\n\n"; exit;
4桁とか数字の種類が9つとかに飽きたらなくなったので、厄介なものを作ってみた。
設定 26 13 2 で104回かかってしまった…。