巨大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回かかってしまった…。