rand関数で被らない値を出す方法

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
RIO

rand関数で被らない値を出す方法

#1

投稿記事 by RIO » 15年前

0~9で被らない数字を3つ出す方法はないでしょうか?

現在、下記の様に実装しているのですが無駄なのでしょうか?
int a = rand%10;
int b = rand%10;
int c = rand%10;

while(1){
    if(a!=b)break;
    else b = rand%10;
}

while(1){
    if(a!=c && b!=c) break;
    else c = rand%10;
}

初級者

Re:rand関数で被らない値を出す方法

#2

投稿記事 by 初級者 » 15年前

rand % 10
で、コンパイルできていますか?

RIO

Re:rand関数で被らない値を出す方法

#3

投稿記事 by RIO » 15年前

すみません。直接書いていたので・・・。
rand()と書いてありコンパイルは通っております。

ロジックがわからないので質問させて頂きました。

バグ

Re:rand関数で被らない値を出す方法

#4

投稿記事 by バグ » 15年前

0~9が格納された配列をシャッフルして、先頭の3つを取り出せばいいですよ。
理屈はトランプを切るのと同じです。

Dixq (管理人)

Re:rand関数で被らない値を出す方法

#5

投稿記事 by Dixq (管理人) » 15年前

バグさんの補足でシャッフルは例えばこんなプログラムでどうでしょう^^
#include<stdio.h> 
#include<stdlib.h>
#include<time.h>

void swap( int *a, int *b ){
    int t = *a;
    *a = *b;
    *b = t;
}

int main(){
    int i=0,r,arr[10]={0,1,2,3,4,5,6,7,8,9};
    srand((unsigned)time(NULL));
    while( i < 10 ){
        r = rand() % 10;
        if( r == i ){    //同じもの交換してもショウガナイ
            continue;    //のでもう一度
        }
        swap( &arr, &arr[[/url] );
        i++;
    }
    for( i=0; i<10; i++ ){
        printf("%d ", arr);
    }
    return 0;
}  

実行結果
2 9 7 4 8 6 3 5 0 1

 
最初の3つを表示させたければ最後のfor文の上限を3にすればいいですね。

Dixq (管理人)

Re:rand関数で被らない値を出す方法

#6

投稿記事 by Dixq (管理人) » 15年前

解り難くてよければ
int main(){
    int i,arr[10]={0,1,2,3,4,5,6,7,8,9};
    srand((unsigned)time(NULL));
    for( i=0; i<10; i++)
        swap( &arr, &arr[(((rand() % 9) + (i + 1)) % 10)] );
    return 0;
}
 
 
これで同じこと出来ますね。

RIO

Re:rand関数で被らない値を出す方法

#7

投稿記事 by RIO » 15年前

皆様ご回答ありがとうございます。 管理人様まで・・・。
こんなに回答が頂けるとは思いませんでした。

なるほど・・・先頭を取るのですか・・・。
そのように考えたことがありませんでした。
ありがとうございました。

たかぎ

Re:rand関数で被らない値を出す方法

#8

投稿記事 by たかぎ » 15年前

(Cではなく)C++を使っていて、rand関数にこだわらないのであれば、std::random_shuffle関数テンプレートを使えばもっと簡単になります。

初級者

Re:rand関数で被らない値を出す方法

#9

投稿記事 by 初級者 » 15年前

同じ値どうしの交換を排除しなくてもよいのでは
ないかと思います。

バグ

Re:rand関数で被らない値を出す方法

#10

投稿記事 by バグ » 15年前

「Fisher-Yates」でググると詳しいことがヒットするかと思います。

たいちう

Re:rand関数で被らない値を出す方法

#11

投稿記事 by たいちう » 15年前

ぱっと見ただけですが、管理人さんの最初のロジックでは、
以下のような数列を生成できないと思います。
偶数回のswapでは不可能でしょう。
(n == 2 の場合を考えるのが簡単でしょう。)

{1,0,2,3,4,5,6,7,8,9};

後で時間が取れたら補足します。
(それまでに誰かの補足がなければ)

たいちう

Re:rand関数で被らない値を出す方法

#12

投稿記事 by たいちう » 15年前

説明しているページを発見。
http://ray.sakura.ne.jp/tips/shaffle.html

バグ

Re:rand関数で被らない値を出す方法

#13

投稿記事 by バグ » 15年前

もう解決したようですがサンプルです。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 10

int main(void)
{
    int i = 0, j = 0, temp = 0, array[N];

    // 乱数の種を設定する
    srand((unsigned)time(NULL));

    // 配列の初期化
    for (i = 0; i < N; ++i)
    {
        array = i;
    }

    // Fisher-Yatesによるシャッフル処理
    for (i = N - 1; i > 1; --i)
    {
        j = rand() % (i + 1);
        temp = array[j];
        array[j] = array;
        array = temp;
    }

    // シャッフルした配列の表示
    for (i = 0; i < N; ++i)
    {
        printf("%d\n", array);
    }

    return 0;
}

閉鎖

“C言語何でも質問掲示板” へ戻る