• ベストアンサー

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

こんにちは、日頃こちらではお世話になっております。 早速、質問で失礼します。 以前こちらで数字を乱数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)の文字列をすべて抜き出しす。必ず正規表現を使用する。 上記のプログラムの作り方&解説等をお願い致します。 続けて質問して申し訳ありませんが宜しくお願いします。

  • Perl
  • 回答数4
  • ありがとう数4

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

  • ベストアンサー
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

  • バブルソートを入れたいのですが

    こんにちは、Perlを始めたばかりの初心者です。 さっそく質問の方失礼します。 乱数1~100までの数字のうち20個をとりだし配列にいれ、数字を昇順に入れ替えして昇順前と昇順後の数字を表示する問題なのですが。 @a[100]=(1..100); srand(time()); for($i=0 ; $i<20 ; $i++){ $a=int(rand(@a)); print"$a\n"; } と上記の乱数20個を取り出すことができたのですが、 そのあとの昇順させようとしてバブルソートを利用したいのですが、どのように組み込めばいいかわかりません。 どのように組み込めばいいのでしょうか? お答えの方ヨロシクお願いします。

    • ベストアンサー
    • Perl
  • クイックソートについて

    下記のソースプログラムのquick_sort_coreの部分がわかりません。 わかる方助けてください。 あとこのソースを降順にした場合の変更点も教えていただけると助かります。 #include <stdio.h> /* printf()利用のため */ #include <stdlib.h> /* rand()利用のため */ #include <time.h> /* clock()利用のため */ #define N 10 /* 整列対象要素数 */ /** * 配列の中身を表示する関数 * @param a 表示する配列 * @param n 配列の要素数 */ void print_array(const int a[], int n) { int i; for (i = 0; i < n; i++) { printf("%d ", a[i]); } printf("\n"); } /** * 整列されているかどうか確認する関数 * @param a 確認対象配列 * @param n 配列の要素数 */ void is_sorted(const int a[], int n) { int i; for (i = 0; i < n - 1; i++) { if (a[i] > a[i + 1]) { printf("昇順に整列されていません\n"); return; } } printf("昇順に整列されています\n"); } /** * クイックソートの本体 * @param a 整列対象配列 * @param l 対象の最初の要素番号 * @param r 対象の最後の要素番号 */ void quick_sort_core(int a[], int l, int r) { /* ここを実装する */ } /** * これまでの整列関数のインターフェースにあわせるクイックソート呼び出し関数 * @param a 整列対象配列 * @param n 配列の要素数 */ void quick_sort(int a[], int n) { quick_sort_core(a, 0, n - 1); } int main(void) { int i; int n = N; /* 整列対象要素数 */ int a[N]; clock_t start,end; /* 0からRAND_MAXの一様乱数をn個生成し、配列aに格納 */ for (i = 0; i < n; i++) { a[i] = rand(); /* 出力確認(print_array)するときは a[i]=rand()%100 としておくと見やすい */ } /* 昇順にソートされているか確認(デバッグ用) */ is_sorted(a, n); /* 配列の中身を確認(デバッグ用) */ print_array(a, n); /* 開始時刻の取得 */ start = clock(); /* クイックソート関数の呼び出し */ quick_sort(a, n); /* 終了時刻の取得 */ end = clock(); /* 配列の中身を確認(デバッグ用) */ print_array(a, n); /* 昇順にソートされているか確認(デバッグ用) */ is_sorted(a, n); /* 実行時間の表示 */ printf("%d 個の要素のクイックソートの実行に %f [秒]かかりました\n", n, (double)(end - start) / CLOCKS_PER_SEC); return 0; }

  • rand関数

    PICをC言語(CCSC)で乱数のプログラムを作りたいと思っています。 乱数ルーチン1 srand(a) i_11=rand() i_12=rand() i_13=rand() . . 乱数ルーチン2 srand(b) i_21=rand() i_22=rand() i_23=rand() . . 乱数ルーチン1をCallした後(電源をOFFしないで)乱数ルーチン2をCallした場合 においてa=bならば i_11,i_12,i_13...i_21,i_22,i_23...は乱数だが i_11=i_21 i_12=i_22 i_13=i_23になってしまう・・・ということでしょうか? もし間違っていたら正解を教えてください。

  • 昇順ソート

    sort.txtから読み込んだ値を 昇順でソートして出力するにはどうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <search.h> /* 比較関数 */ int strcmp_asc(const void *, const void *); int main(void) { FILE *fin, *fout; int i; int length; char s[256], s2[256]; if( (fin=fopen("sort.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s, 256, fin) != NULL) { /* 要素数を求める */ length = sizeof(s) / 256; /* 昇順でソート */ qsort(s, length, 256, strcmp_asc); /* memset(s2, NULL, sizeof(s2)); for (i = 0; i < length; i++) { } */ fprintf(fout,"%s\n",s2); } fclose(fin); fclose(fout); return 0; } int strcmp_asc(const void *sa, const void *sb) { return strcmp((char *)sa, (char *)sb); } sort.txt 50 45 35 25 15 10 5 1 32 46 8 7 9 19 18 14 16 13 12 17 11 20 40 30 31 3 2 37 38 36 33 39 34 49 47 48 4 6 44 42 43 41 21 22 26 24 28 29 27 23

  • Perlの乱数について

    RedHat Linux ES2.1のperl v5.6.1にて初めてのプログラムを書いているものです。 Oracle9iに格納するDATE型のデータを大量に乱数にて作成しようとしているのですが、うまくいきません。 作成しようとしているのは2004年度か2005年度のある日付です(30日まで)。 例) 04-01-30 05-07-12 04-09-28 04-12-11 質問1.下のプログラムだと、年度が00,01,02,03,04,05の値をとり得てしまう。これを04か05に限定するにはどうすればよいか。 質問2.月・日が1桁の場合は0を頭につけたい。下のプログラムでは05-12-1となったり04-5-30となったりしてしまう。 #!/usr/bin/perl $a = 1; while($a < 100000){ $year_rand = int(rand(5)); $month_rand = int(rand(12))+1; $day_rand = int(rand(30))+1; print "0$year_rand-"; print "$month_rand-"; print "$day_rand,"; print "\n"; $a = $a+1; } 宜しくお願い致します。

    • ベストアンサー
    • Perl
  • 配列のソート(昇順)

    最大で30個の整数データを入力し、それを大きい順に並べ替えるプログラムを1次元配列と繰り返し・if文を使って作成しなさい。 という問題で #include<stdio.h> main() { int a[30],x,y,z; printf("Seisu wo 30 ko Nyuryoku \n"); for(x=0;x<=29;x++) scanf("%d",&a[x]); printf("before sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); for(x=0;x<=28;x++) for(y=0;y<=28-x;y++) if(a[y]<a[y+1]) { z=a[y];a[y]=a[y+1];a[y+1]=z; } printf("\n after sort...\n"); for(x=0;x<=29;x++) printf("%d ",a[x]); } ここまで出来たのですが最大で30個ということなので(例)「10個の整数を入力して Z を入力したら終了」 としたいのですがどこをどのようにすればいいですか?

  • [perl]正規表現を用いた置換を引数で与えて行いたい

    正規表現で置換を行いたいのですが、後方参照などがうまくいきません。 ---------------------------------------------------- $string = hogehogehoge; $before = (ho); $after = a\1; $string =~ s/$before/$after/g; ←ここの正しい書き方がわからない print "string = $string\n"; ---------------------------------------------------- string = ahogeahogeahoge このような出力結果を得たいのですが string = a\1gea\1gea\1ge のようになってしまい\1が参照されません。 おそらく基本的なことなのでしょうが調べてみても分かりませんでした。 もし他にも使えない記述がありましたら、それも含めて書けるやり方を教えていただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • JAVAで配列を使って * を縦向きのグラフで表示したいです。

    JAVAの勉強をしています。 このプログラムは配列に乱数を生成して * を 横向きにするプログラムです。 練習問題で、以下のプログラムを書き換えて、* を縦向きのグラフで表示する問題なのですが、解く方法がわかりません。 どなたか答えもしくはヒントを下さい。 よろしくお願いします。 import java.util.Random; import java.util.Scanner; public class Test06_04 { public static void main (String[] args) { Random rand = new Random(); Scanner stdIn = new Scanner(System.in); System.out.print("要素数 : "); int n = stdIn.nextInt(); //要素数を読み込む int[] a = new int[n]; //配列を生成 for (int i = 0; i < n; i++) { a[i] = 1+ rand.nextInt(10); } for (int i = 0; i < n; i++) { System.out.print("a[" + i + "] : "); for (int j = 0; j < a[i]; j++) System.out.print('*'); System.out.println(); } } }

    • ベストアンサー
    • Java
  • シェルソート(Cプログラミング)

    シェル・ソート 基本挿入法により、データを昇順にソートする。 というプログラムを実行したいと思ったのですが、エラーがでてしまいコンパイルできません。 書いたプログラムは以下の通りです。 #include<stdio.h> #include<math.h> #define N 100 int main (void) { int a[N],i,j,t; for (i=0;i<N;i++) a[i]=rand(); for (i=1;i<N;i++){ for (j=j-1;j>=0;j--){ if (a[j]>a[j+1]){ t=a[j]; a[j]=a[j+1]; a[j+1]=t; } else break; } } for (i=0;i<N;i++) printf("%8d",a[i]); } エラーメッセージは以下のようにでました。 警告 W8065 sample.c 10: プロトタイプ宣言のない関数 'rand' の呼び出し(関数 main ) 警告 W8070 sample.c 22: 関数は値を返すべき(関数 main ) どうすれば出来るのでしょうか、お答えよろしくお願いします。

  • 主キーソート(キーの優先順位をつけてソート)

    時刻から生成した乱数を、構造体「TEST」のメンバ変数 a, b, c に代入し、 メンバb を基準にして、昇順にクイックソートしてみます。 #include <stdio.h> #include <stdlib.h> #include <time.h> typedef struct{ int a; int b; int c; }TEST; int comp( const void *c1, const void *c2 ); int main(void) { int i; TEST base[10]; /* 乱数の生成 */ srand( (unsigned int)time( NULL ) ); for( i=0; i<10; i++ ){ base[i].a = rand() % 100; /* 0~99の乱数 */ base[i].b = rand() % 100; base[i].c = rand() % 100; printf( "%d¥t", base[i].a ); printf( "%d¥t", base[i].b ); printf( "%d¥t", base[i].c ); printf( "¥n" ); } /* TEST構造体のbを基準にソート */ printf( "¥n--TEST構造体のbを基準にソート--¥n¥n" ); qsort( base, 10, sizeof(TEST), comp ); /* ソート後のデータを表示 */ for( i=0; i<10; i++ ){ printf( "%d¥t", base[i].a ); printf( "%d¥t", base[i].b ); printf( "%d¥t", base[i].c ); printf( "¥n" ); } return 0; } /* 比較関数 */ int comp( const void *c1, const void *c2 ) { TEST test1 = *(TEST *)c1; TEST test2 = *(TEST *)c2; int tmp1 = test1.b; /* b を基準とする */ int tmp2 = test2.b; return tmp1 - tmp2; } ランダム結果 13 22 21 63 21 45 52 45 81 75 67 94 7 1 44 81 66 38 35 24 35 62 6 4 76 12 84 86 77 71 --TEST構造体のbを基準にソート-- 7 1 44 62 6 4 76 12 84 63 21 45 13 22 21 35 24 35 52 45 81 81 66 38 75 67 94 86 77 71 と、このように表示されます。 下段の真ん中の列を見ると、メンバ変数 b で並び替えられている事が分かります。 比較関数comp内では、TEST構造体でキャストしてから、bを取り出しています。 また、戻り値に「tmp1 - tmp2」を使うことで、 「a < b :負の値、a == b :0、 a > b :正の値」という条件に当てはめています。 とhttp://simd.jugem.jp/?eid=116で書かれていますが これはb列を基準にしたソートであり、a列とc列の優先順位は書かれていません キーの優先順位をb>a>cにするにはどうしたらよいでしょうか。 もっとたくさんキーあった時(a>b>c>d>e>f>g・・・)のようにキーの優先順位つけて昇順or降順にデータをソートしたいです。 よろしくお願いします

専門家に質問してみよう