30764


下記のコード（mainやincludeの部分は省略してます）で実行するとprintfが出力されず、プログラムも最後まで動かなくて止まりません。  
コンパイルでは成功してて警告やエラーも出てません。  
ずっと考えて少しずつ修正を加えたり試してるのですが、全然作れそうにないです。  
どうすればタイトルのような機能を作れますか？

コード：

[code]

    int len = 63;
    int place[len];
    struct timeval tv;
    
    for(int i=0; i<len; i++) {
        gettimeofday(&tv, NULL);
        srand((unsigned int)tv.tv_sec * ((unsigned int)tv.tv_usec + 1));
        place[i] = rand() % 62;
    }
    
    int f=0;
    for(int i=0; i<len; i++) {
        while(1) {
            f=0;
            for(int j=0; j<i; j++) {
                if(place[i] == place[j]) f=1;
            }
            if(f==1) {
                gettimeofday(&tv, NULL);
                srand((unsigned int)tv.tv_sec * ((unsigned int)tv.tv_usec + 1));
                place[i] = rand() % 62;
            } else {
                printf("%d ", place[i]);
                break;
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2016-11-29T06:58:36.780
30763
2016-11-29T08:32:32.567
2016-11-29T07:35:35.290
13313
13313
question
c
(C言語)全ての数値が被らなくなるまで乱数を生成して配列に格納する方法


本題から外れるから部分(`srand()` の使い方がおかしいとか)は置いておくとして、単純に `place` が要素数 63 個の配列なのに

[code]

    place[i] = rand() % 62;
    
[/code]

で取りうる値が 0 ~ 61 の 62 通りしかないので、`while(1)` から抜けることはありえません。`rand()` のところは２箇所とも

[code]

    place[i] = rand() % len;
    
[/code]

とすればいいと思います。


CC BY-SA 3.0
2016-11-29T07:20:40.853
30764
2016-11-29T07:20:40.853
2521
30763
answer


@TatzSekine さんは問題の所在を言及していました。こちらの意見も察してほしい。

乱数を1つずつ生成して、重複しないまで走らせて、恐らく、多くの時間がかかります。（`len = 10000` と試したら、２秒ぐらいかかってしまいました）

こちらの考えは、被らない配列を作って、そして数字をシャッフルすることです。すなわち

[code]

    int len = 63;
    int mod = len;
    int place[len];
    struct timeval tv;
    
    gettimeofday(&tv, NULL);
    // 最初に一度 srand 初期化すれば良いです
    srand((unsigned int)tv.tv_sec * ((unsigned int)tv.tv_usec + 1));
    
    for(int i = 0; i < len; ++i) {
        place[i] = i;
    }
    
    int x, y, j, tmp;
    // 何回交換して十分にランダムになれますか、試してみたら、len と同じと良い
    int swap_times = len;
    for (j = 0; j < swap_times; ++j) {
        x = rand() % len;
        y = rand() % len;
        tmp = place[x];
        place[x] = place[y];
        place[y] = tmp;
    }
    
[/code]


CC BY-SA 3.0
2016-11-29T08:05:38.217
30765
2016-11-29T08:05:38.217
18621
30763
answer


単に `0` から `len-1` までの数字の順序をランダムに並べ替えたいということなら、もっと効率よく書くことができると思います。

[code]

        for (int i = 0; i < len; i++) {
                place[i] = i;
        }
        for (int i = 0; i < len; i++) {
                int j = i + (rand() % (len - i));
                // swap(place[i], place[j]);
                int tmp = place[i];
                place[i] = place[j];
                place[j] = tmp;
        }
    
[/code]

参考: [フィッシャー -
イェーツのシャッフル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC_-_%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB)


CC BY-SA 3.0
2016-11-29T08:32:32.567
30766
2016-11-29T08:32:32.567
9873
30763
answer