乱数で例えば0〜5の数字を作り、if文でその数字によって処理を分岐させているのですが、たとえばif文の中の処理を
10回読んだらその処理を呼びたくありません。つまり乱数の3のif文が10回呼ばれたら、0,1,2,4,5というような乱数を
生成したいです。
現在、Swiftで作っているのですがC/C++でも構わないので乱数の飛ばし方、もしくはいい方法などがあれば教えていただきたいです。
C
1 2for(int i = 0; i < 50; i++) { 3 srand((unsigned int)time(NULL)); 4 int n = rand() % 6; 5 6 if(n == 0) { 7 処理1 // 10回呼ばれたらn == 0を呼びたくない 8 } 9 else if(n == 1) { 10 処理2 // 10回呼ばれたらn == 1を呼びたくない 11 } 12 else if(n == 2) { 13 処理3 // 10回呼ばれたらn == 2を呼びたくない 14 } 15 else if ... すべてランダムに10回ずつ読んで終了 16} 17
よろしくおねがいします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答8件
0
もとから10個づつ作っておいて取り出す方が意図が伝わりやすくないですか?
swift
1let seq = Array(repeating: 0...5, count: 10) 2 .flatMap { $0 } 3 .shuffled() 4 5for n in seq { 6 switch n { 7 case 0: 処理1() 8 ... 9 ... 10 case 5: 処理5() 11 default: () 12 } 13}
投稿2022/02/19 07:15
総合スコア3384
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/02/20 04:01
0
C
1#include <stdio.h> // printf, putchar 2#include <stdlib.h> // srand, rand 3#include <string.h> // memset 4#include <time.h> // time 5 6int main(void) 7{ 8 char a[6 * 10]; 9 for (int i = 0; i < 6; i++) memset(a + i*10, i, 10); 10 srand(time(0)); 11 int i = 60; 12 while (i > 0) { // 50回実行したければ (i > 10) 13 int j = rand() % i, n = a[j]; 14 a[j] = a[--i]; 15 printf(" %d", n); // 処理(n+1)を実行 16 } 17 putchar('\n'); 18}
投稿2022/02/19 06:28
総合スコア8224
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
各値の呼び出し回数を記録しておき、上限に達した値を取り除いていく方法もあります。
C++
1#include <iostream> 2#include <vector> 3#include <numeric> 4#include <random> 5 6int main() 7{ 8 const int VAL_CNT = 6; 9 const int LOP_CNT = 50; 10 const int MAX_CNT = 10; 11 12 std::vector<int> counts(VAL_CNT); // 呼び出し回数を保持 13 std::vector<int> vals(VAL_CNT); 14 std::iota( vals.begin(), vals.end(), 0);// 乱数で得たい値 0, 1,... 15 16 std::random_device rnd; 17 for( int i = 0; i < LOP_CNT; i++){ 18 19 // 乱数で位置によって値を得る 20 int pos = rnd() % vals.size(); 21 int n = vals[pos]; 22 23 // nによる処理 24 std::cout << n << std::endl; 25 26 // 呼び出し上限回数を満たした値を取り除く 27 counts[n]++; 28 if( counts[n] >= MAX_CNT){ 29 std::cout << "remove " << n << std::endl; 30 vals.erase(std::remove(vals.begin(), vals.end(), n), vals.end()); 31 32 // 初期条件(VAL_CNT * MAX_CNT < LOP_CNT)により弾切れで続行できなくなる場合あり 33 if( vals.size() == 0){ 34 break; 35 } 36 } 37 } 38 39 // 確認 40 std::cout << "counts" << std::endl; 41 for( int i = 0; i < counts.size(); i++){ 42 std::cout << i << ":" << counts[i] << std::endl; 43 } 44 return 0; 45}
投稿2022/02/19 03:24
総合スコア38266
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
①出目とカウントのpairをvectorで保持
std::vector<std::pair<int,int>> v(6)
②vectorをシャッフル
std::shuffle( v.begin(),v.end(),engine ) → engine:乱数生成器
③v.size()以下の乱数nを生成
v[n].first → 出目
v[n].second++ → カウントを増やす
④カウントが10になったらvectorから削除
std::iter_swap( v.begin()+n, v.end()-1 )→n番目の要素を最後の要素と交換
v.pop_back()→最後の要素を削除
③④を繰り返す
投稿2022/02/19 02:55
編集2022/02/19 03:02総合スコア581
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
こんなやりかたもアリっちゃアリかと
C++
1#include <iostream> 2#include <vector> 3#include <numeric> 4#include <random> 5 6int main() { 7 std::vector<int> dice; 8 9 std::vector<int> v(6); 10 std::iota(v.begin(), v.end(), 0); // v = [ 0 1 ... 5 ] 11 for ( int i = 0; i < 10; ++i ) { // dice = 10個のv 12 dice.insert(dice.end(), v.begin(), v.end()); 13 } 14 std::random_device seed_gen; 15 std::mt19937 engine(seed_gen()); 16 std::shuffle(dice.begin(), dice.end(), engine); // diceの要素をかき混ぜる 17 18 for ( int value : dice ) { 19 std::cout << value << ' '; 20 } 21}
投稿2022/02/18 22:54
総合スコア16614
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
こんな感じでしょうか。
swift
1// 出た目の回数をカウントするための配列 2var count = Array(repeating: 0, count: 6) 3 4for i in 0..<50 { 5 var n: Int 6 repeat { 7 n = Int.random(in: 0..<6) 8 } while count[n] >= 10 // すでに 10 回以上出たものはやり直し 9 10 // 出た目の回数を増やす 11 count[n] += 1 12 13 // n を使った処理 14}
なお、Swift では srand は不要ですが、C でもループで毎回 srand するのは無意味です。
追記: 別解として、こんなのもありかな?
swift
1var count = Array(repeating: 0, count: 6) 2 3for i in 0..<50 { 4 // 0 〜 5 のうち、まだ 10 回出てないものの配列を作り、その中からランダムに選ぶ 5 let n = (0..<6).filter { count[$0] < 10 }.randomElement()! 6 7 count[n] += 1 8 9 // n を使った処理 10}
投稿2022/02/18 20:05
編集2022/02/18 20:36総合スコア7895
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。