去年卒業しましたたまのびです。
このブログってOB投稿ありですかね?問題があれば削除してください。
~重複しないように乱数を得る方法~
整数について乱数を作成すると、数が重複する場合があります。巡回セールスマン問題の巡回経路を決定するときなど、重複する場合問題が発生する場合があります。そんなときにはこれ!!/************************************************* 関数 :undupRnd(min,max,dest,n) 機能 :最小値min,最大値maxの整数列の中からn個だけ 無作為に取り出し配列destに格納 戻り値:destの先頭アドレス 備考 :rand()関数を内部で使用 *************************************************/ int *undupRnd(int min,int max,int *dest,int n){ int i; int *array; int size = max - min +1; if( NULL == dest ){ fprintf(stderr,"格納先が不正[%s:%s]\n",__FILE__,__LINE__); return NULL; } if( size < n ){ fprintf(stderr,"取り出す数が取り出す範囲より大きい[%s:%s]\n",__FILE__,__LINE__); return NULL; } if( NULL == (array = (int*)calloc(size,sizeof(int))) ){ fprintf(stderr,"配列が確保できない[%s:%s]\n",__FILE__,__LINE__); return NULL; } //勢数列の配列を順番に。 for(i=0;i<size;i++){ array[i] = i+min; } for(i=0;i<n;i++){ int index = rand()%(n-i); dest[i] = array[index];//抽出 array[index] = array[n-i-1];//上書き } free(array); return dest; }
簡単にC言語プログラミングしてみました。
実際にコンパイルして使ってみてください。重複しない整数乱数列を生成できます。
このアルゴリズムは至極簡単なものです。
- 連続する整数列(取り出す対象)を配列に確保する
- 乱数を用いて取り出す要素の添え字を決める
- 取り出して格納する。
- 取り出した要素を配列の端っこの要素で上書き(これで同じ値は取り出されなくなる)
- 次に添字を選ぶときは範囲を1だけ狭める(これで同じ値は取り出されなくなる
4と5によって同じ値が取り出されるのを阻止しています。
関数中での引数nとsize(max-min+1)が等しい(n=size)のとき、この関数は整数を無作為に並び替える機能を持つと言えます。こう考えると用途は広がりそうですね。どんどん使ってみてください。