• ベストアンサー

ソートを利用して文字を昇順で入れ替えしたいのですが

こんにちは、日頃こちらではお世話になっております。 早速、質問で失礼します。 以前こちらで数字を乱数1~100の間の20個をとりだし昇順前と昇順後を表示させるやり方を教えてもらって、このプログラムを少し変えて 『乱数(AA,AB,AC...BA..BV..ZZ)を20個取り出す』 プログラムを作ろうとしていまして乱数の20個を取り出す所までいけたのですがその後の昇順で詰まってしまいます。 @ab=(A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z); srand(time()); for($i=1;$i<=20;$i++){ $a=int(rand()*26); $b=int(rand()*26); $string = $ab[$a] . $ab[$b]; print "$string\n"; } この後に @after = sort { $a <=> $b } @before; print "before:\n"; print join(",",@before) ; print "\nafter:\n"; print join(",",@after) . "\n"; 入れるのはわかるのですが for(){    (1)     } の間にどう組み込めば良いのでしょうか? それと追加質問で申し訳ないのですが (1)自分で、英字を入力して、20個の数字から探すプログラムを作って、見つかった場合には、配列の何番目に入っていたかを出力。入っていない場合には、"見つかりません"と出力して、再度入力させる。 (2)20個の数字からD?(DA,DB,DC,DD,DE...DZ)の文字列をすべて抜き出しす。必ず正規表現を使用する。 上記のプログラムの作り方&解説等をお願い致します。 続けて質問して申し訳ありませんが宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#11136
noname#11136
回答No.4

最初に示された方法だと、AAからZZの中からランダムに取りだした20個の中で、重複するものが出てき得るのではないでしょうか(それでいいのかもしれませんが)? 重複しないように、全ての場合のリストsourceから抽出していく感じで、20個のリストbeforeを作ってもいいと思います。 @source = AA..ZZ; foreach (1..20) { $index = int(rand(@source)); push(@before, splice(@source, $index, 1)) } @after = sort { $a cmp $b } @before; print "before: @before\n"; print "after: @after\n"; { do { print "What? "; chomp($findword = <STDIN>); } while ($findword !~ /^[A-Z]{2}$/); $getid = "見つかりません"; foreach $id (0..$#before) { $getid = $id if $findword eq $before[$id]; } if ($getid eq "見つかりません") { print "$getid\n"; redo } } print "index of $findword: $getid\n"; @getlist = grep /^D/, @after; print "list of D*: @getlist\n";

terunosuke
質問者

お礼

見やすいプログラムを有難うございます。 参考にさせていただきます。

その他の回答 (3)

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>さっそく指示されたところを書き換えてみたのですが、昇順になりませんでした。 配列への追加の仕方を書いたのであって、ソートとは直接関係ありません。 #2の方が指摘されているように、文字列の比較には、cmpを使います。

terunosuke
質問者

お礼

なるほど、そういう意味だったのですね。 ご指摘されたところを直しら動きました。 有難うございます。

  • steel_gray
  • ベストアンサー率66% (1052/1578)
回答No.2

追加質問はちょっと読解できなかったのでその前まで。 以下サンプル。 my @ab=(A..Z); # 範囲演算子を使いましょう。(見易さと単純なタイプミス防止) # ちなみに AA..ZZ と書いてしまう事もできます。 srand(time()); my @before; for my $i (1..20){ # 同じように 1~20 である事を直感的にわかりやすく。(for(;;)も古くからある形式なのでこれは強くは勧めませんが) $a=int(rand()*26); $b=int(rand()*26); my $string = $ab[$a] . $ab[$b]; push @before,$string; # 配列に追加。(質問に対する純粋な回答はこれ1行) } my @after = sort { $a cmp $b } @before; # 文字列の比較の場合には <=> ではなく、cmp を使います。 print "before:\n"; print join(",",@before) ; print "\nafter:\n"; print join(",",@after) . "\n"

terunosuke
質問者

お礼

解りやすいご解説を有難うございます。 参考にさせていただきますね。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

1個のデータができたところ print "$string\n"; で push @before , $string; してやればいいです。 追加(1) 普通は、頭から検索して見つかればその時のインデックスを表示します。 件数が多い場合は、2分検索とかするのかもしれませんが、20個程度だったら単純にループして探せばいいです。 追加(2) 方法は、色々あると思いますが、grepを使うのが簡単です。 @select = grep /D[A-Z]/, @before; とでもすればいいと思います。

terunosuke
質問者

お礼

返信ありがとう御座います。 さっそく指示されたところを書き換えてみたのですが、昇順になりませんでした。

関連するQ&A