プロが教えるわが家の防犯対策術!

Excelで乱数を使って、100個のセルにそれぞれ1~5までの数字をランダムに割り当てるようにするにはどうすればよいでしょうか?ただ、以下の条件があります。

全体で1~5の数字の出る個数は次のように決まっている。
1:30回
2:25回
3:20回
4:15回
5:10回

回答お待ちしております。

A 回答 (12件中1~10件)

こんなのはいかがでしょうか?


--------------------------------------------------------------------------------
Sub 乱数発生()
Dim 行 As Long
Dim 有(0 To 99) As Boolean
Dim 仮 As Long
For 行 = 1 To 100
Do
仮 = Int(100 * Rnd)
Loop Until 有(仮) = False
Cells(行, 1).Value = 仮
有(仮) = True
Next
For 行 = 1 To 100
Select Case Cells(行, 1).Value
Case Is < 30
Cells(行, 1).Value = 1
Case Is < 55
Cells(行, 1).Value = 2
Case Is < 75
Cells(行, 1).Value = 3
Case Is < 90
Cells(行, 1).Value = 4
Case Else
Cells(行, 1).Value = 5
End Select
Next
End Sub
--------------------------------------------------------------------------------
    • good
    • 1
この回答へのお礼

ありがとうございます!

行ごとに1~100でランダムを取って、その数に応じて1~5を当てはめる。
次の行では上の行で出た値を除いて1~100のランダムを取って1~5を当てはめる。
これを100行繰り返す。
といった感じでしょうか。
違っていたらすみません。

これなら1~5の数字の出る回数を変更することも簡単にできそうです。
ありがとうございます!

お礼日時:2017/12/18 22:10

No6の方が既に回答を書いてますが、別解です。


標準モジュールに登録してください。
表示されているシートのA1~A100に1~5の値を割り当てます。(割り当てる回数は30, 25, 20, 15, 10個です)

Option Explicit
Public Sub ランダム割り当て()
'1~5の数字をA1~A100に割り当てる
Dim ar0 As Variant
Dim ar1 As Variant
Dim maxelm As Long
Dim i As Long
Dim j As Long
Dim ix As Integer
ar0 = Array(1, 2, 3, 4, 5) '表示したい数 1,2,3,45
ar1 = Array(30, 25, 20, 15, 10) '表示したい数(1,2,3,4,5)に割り当てる出現回数(合計が100になること)(出現回数を変える場合はこの値を変えること)
maxelm = 4
Randomize '乱数初期化
For i = 1 To 100
ix = Int(Rnd * (maxelm + 1))
Cells(i, "A").Value = ar0(ix)
ar1(ix) = ar1(ix) - 1
If ar1(ix) = 0 Then
For j = ix To maxelm - 1
ar1(j) = ar1(j + 1)
ar0(j) = ar0(j + 1)
Next
maxelm = maxelm - 1
End If
Next
End Sub
    • good
    • 1
この回答へのお礼

回答ありがとうございます!
出現回数を頻繁にいじる場合にとても使いやすそうです。
こちらも試してみます!

お礼日時:2017/12/18 23:47

No.5です。



>結果はA列に一列に出ると嬉しいです。

No.6さんのコードがスマートなので似たような感じになりました。

Sub Sample2()
Dim i As Long, c As Range, myNum As Long
Dim myFlg(1 To 100) As Boolean
Randomize
For Each c In Range("A1:A100")
For i = 1 To 100
Do
myNum = Int(100 * Rnd + 1)
Loop Until myFlg(myNum) = False
Next i
Select Case myNum
Case Is <= 30
c = 1
Case Is <= 55
c = 2
Case Is <= 75
c = 3
Case Is <= 90
c = 4
Case Else
c = 5
End Select
myFlg(myNum) = True
Next c
End Sub

※ やり方はNo.6さんと同じやり方です。
まず、1~100までの乱数を重複なしに発生させ
結果が
30以下の場合 → 1
55以下の場合 → 2
75以下の場合 → 3
90以下の場合 → 4
100以下(上記以外)の場合 → 5

にしています。m(_ _)m
    • good
    • 1
この回答へのお礼

丁寧な回答ありがとうございます!
このパターンが一番シンプルなようですね。

お礼日時:2017/12/18 23:51

「100」になっている3ヶ所を「148」にして、「Dim 有(0 To 99) As Boolean」を「Dim 有(0 To 147) As Boolean」にして、2回目のループの割合を直すだけです。

    • good
    • 1
この回答へのお礼

回答ありがとうございます。
丁寧に教えてくださり大変助かりました!
素直に148倍すればいいということですね。

お礼日時:2017/12/18 23:47

No.6 のお礼について



No.7にも書きましたがちょっと違っています。もう少し説明すると
1回目のループは
① 乱数を発生させそれを100倍した物の整数の部分だけ取り足します
② 0~99が使われたかのフラグ(変数「有()」)を見て使われていなければセルに仮数としてセットして次の行へ
③ 使われていたら①から繰り返します
④ 100行目まで繰り返します(0~99の重複の無い乱数が仮にセットされています)
2回目のループは
⑤ 仮の数値が30未満だったら「1」をセットします
⑥ 仮の数が30以上55未満ならば「2」をセットします
⑦ 仮の数が55以上75未満ならば「3」をセットします
⑧ 仮の数が75以上90未満ならば「4」をセットします
⑨ 仮の数が90以上なら「5」をセットします

※ 2回目のループはご察しの通りです。
    • good
    • 1
この回答へのお礼

詳しい説明ありがとうございます!とても分かりやすいです。

もう一つ、
もし仮に、全体数を100から148など中途半端な数に増やした場合についてです。
この場合乱数を100倍するだけではうまくいかなくなる気がするのですが、こういった場合はどうするのが良いのでしょうか?

何度もすみません。

お礼日時:2017/12/18 22:48

≫ 全体で1~5の数字の出る個数は次のように決まっている。


1の出る個数が5のそれの3倍というのは「ランダムに割り当て」にはなってない!と断言しますが、貴方は「いや、そんなことはない!」と主張するのですか?
    • good
    • 2
この回答へのお礼

回答ありがとうございます。
確かに「ランダムに割り当て」とは言えないですね。
「組み合わせの中の1パターンを100個のセルに表示させたい」と言うべきだったかもしれません(汗

お礼日時:2017/12/18 23:58

No.6 の説明です



1回目のループで0~99の重複の無い乱数をセルにセット
2回目のループで割合に応じて数をセットし直しています。
    • good
    • 1
この回答へのお礼

はじめに乱数を重複なくセットしてるんですね!プログラムに詳しくないので、説明してくださると非常に助かります。
ありがとうございます!

お礼日時:2017/12/18 22:14

こんばんは!



VBAになりますが、一例です。
>100個のセルに・・・

A1~J10セルの範囲としました。

Sub Sample1()
Dim i As Long, k As Long, cnt As Long
Dim c As Range, myNum As Long
Dim myFlg(1 To 100) As Boolean, myAry
myAry = Array(1, 2, 3, 4, 5)
For k = 0 To UBound(myAry)
Select Case myAry(k)
Case 1
Do Until cnt = 30
cnt = cnt + 1
Cells(cnt, "K") = myAry(0)
Loop
Case 2
Do Until cnt = 55
cnt = cnt + 1
Cells(cnt, "K") = myAry(1)
Loop
Case 3
Do Until cnt = 75
cnt = cnt + 1
Cells(cnt, "K") = myAry(2)
Loop
Case 4
Do Until cnt = 85
cnt = cnt + 1
Cells(cnt, "K") = myAry(3)
Loop
Case Else
Do Until cnt = 100
cnt = cnt + 1
Cells(cnt, "K") = myAry(4)
Loop
End Select
Next k
Randomize
For Each c In Range("A1:J10")
For i = 1 To 100
Do
myNum = Int(100 * Rnd + 1)
Loop Until myFlg(myNum) = False
Next i
c = Cells(myNum, "K")
myFlg(myNum) = True
Next c
Range("K:K").ClearContents
End Sub

※ K列を作業列として使用していますので、
K列は使っていない状態にしておいてください。

※ どこかの列にあらかじめ 1を30、2を25、3を20・・・
と羅列しておけばもっと短いコードで可能です。m(_ _)m
    • good
    • 1
この回答へのお礼

回答ありがとうございます!

試してみたところ、4が10個、5が15個あるようです。
多分ですが、
Do Until cnt = 85
の部分を90にすれば問題ないのですかね?
間違っていたらすみません。

ちなみに、どこかの列にあらかじめ数字を入れておく場合だとどのようになるのでしょうか?
また、結果はA列に一列に出ると嬉しいです。

注文が多くて申し訳ないです。

お礼日時:2017/12/18 22:34

いろんなやり方がありますが、一番短いプログラミングとして思いつくのは、、、


長さ100の配列に上記の数字を格納し、ランダムの位置で切って順番を入れ替えて繋ぎなおすということを100回位やればいいんじゃないかな? セルに文字を書き込むのはまあ、できるでしょう。
    • good
    • 1
この回答へのお礼

回答ありがとうございます。なるほど、これを繰り返していくとどんどん混ざっていってランダムになるということですね。偏りのある状態から、完全に混ざっていく過程を文字列として出したい場合にはいいかもしれません。

お礼日時:2017/12/18 21:41

マクロ(VBA)を使用しても良いですか?

    • good
    • 0
この回答へのお礼

回答ありがとうございます。マクロの使用でも大丈夫です!

お礼日時:2017/12/18 21:09

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!