2011年12月25日日曜日

[ExcelVBA] n人中m人が当選するくじ その2


■お題
n人中m人が当選するくじ除(問題出典:どう書く?org)
- 問題詳細 -
n人の中から公平にm人を選ぶ、くじ引きプログラムを作ってください。

■解答例
□Collectionオブジェクトを使ってみる
シャッフルするためにあらためてコードを書くなんてめんどくさいですね。
Collectionオブジェクトなら、.Countの数を上限に乱数で要素を選択して.Removeで要素を削除しての繰り返しでよさそうですね。

では、コードです。
モジュール名:SubModule
  1. Option Explicit  
  2.   
  3. Function lot(n As Integer, m As IntegerAs Variant  
  4.     Randomize  
  5.       
  6.     Dim list As New Collection  
  7.     Dim i As Integer  
  8.     
  9.     For i = 1 To n  
  10.         list.Add i  
  11.     Next  
  12.       
  13.     Dim result() As variant, r As Integer  
  14.     ReDim result(m - 1)  
  15.       
  16.     For i = 0 To m - 1  
  17.         r = Int(Rnd() * list.Count) + 1  
  18.         result(i) = list.Item(r)  
  19.         list.Remove (r)  
  20.     Next  
  21.       
  22.     lot = result  
  23. End Function  
3行目:引数 n…参加者全員の数を指定、m…選ばれる人数を指定
4行目:乱数のシードを変更する。Randomize(Number) Numberは省略可。省略時、時刻からシード値を取得。
6行目:変数 list・・・参加者の人数分値を用意しておく。
7行目:変数 i・・・For文で使用。

9行目~11行目:人数文、Collectionオブジェクトに追加する

13行目:変数 result・・・当選者の番号を格納するよう
            変数 r・・・乱数を格納するよう
14行目:result配列の要素を確定する
17行目:乱数を生成する。ただし、Collectionオブジェクトの要素は1から始まるので1以上オブジェクト.Count以下で生成。
18行目:乱数の値を元にCollectionオブジェクトの値を当選者としてresult変数に格納する
19行目:.removeメソッドで削除する
20行目:繰り返し
22行目:返り値としてresult配列を返す



実際にこんな感じで使う

モジュール名:MainModule
  1. Option Explicit  
  2.   
  3. Sub main()  
  4.     Dim result As Variant  
  5.     result = lot(10, 3)  
  6.       
  7.     Dim i As Integer  
  8.     For i = 0 To UBound(result)  
  9.         Debug.Print result(i)  
  10.     Next  
  11.       
  12.     Debug.Print "-------------"  
  13. End Sub  


実行結果
  1. 2   
  2.  10   
  3.  1   
  4. -------------  
  5.  2   
  6.  4   
  7.  8   
  8. -------------  
  9.  2   
  10.  9   
  11.  7   
  12. -------------  
  13.  5   
  14.  9   
  15.  3   
  16. --------------  

0 件のコメント: