Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Aug 23rd, 2012  |  syntax: None  |  size: 1.63 KB  |  hits: 7  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. case class Item(label: String, weight: Int)
  2.  
  3. // | アイテム | 重み |
  4. // | a       | 1 |
  5. // | c       | 3 |
  6. // | b       | 2 |
  7. val items = List(
  8.   Item("a", 1),
  9.   Item("c", 3),
  10.   Item("b", 2)
  11. )
  12.  
  13. val distribution = items.foldLeft((0, List.empty[(Item,Int)])) { (res,item) =>
  14.   val sum = res._1 + item.weight
  15.   (sum, res._2 :+ (item, sum))
  16. }
  17.  
  18. // res: (Int, List[(Item, Int)]) = (6,List((Item(a,1),1), (Item(c,3),4), (Item(b,2),6)))
  19.  
  20. // | アイテム | 重み |
  21. // | a       | 1 |
  22. // | c       | 3 |
  23. // | b       | 2 |
  24. // から
  25. // | アイテム | 累積重み |
  26. // | a       | 1 |
  27. // | c       | 4 |
  28. // | b       | 6 |
  29. // という分布 distribution を作成したことになる。
  30.  
  31. /** 0以上6未満の乱数を生成する */
  32. def random = {
  33.   val r = math.random
  34.   r * distribution._1
  35. }
  36.  
  37. // 0以上6未満の乱数が、以下の数直線上のどこにプロットされるかを考える。
  38. //
  39. // 0__1________5__6
  40. //
  41. // 乱数rより大きい累積重みを左から順に探せばよい。
  42. // すると、
  43. // 0 <= r < 1 なら a
  44. // 1 <= r < 4 なら c
  45. // 4 <= r < 6 なら b
  46. // が選択される。
  47. // a,b,cそれぞれに対してrの値域を計算してみると、それぞれ1:3:2となる。
  48. // 乱数が一様分布にそっていれば、a,b,cの出現する割合も1:3:2となるはずである。
  49. def sample: Item = {
  50.   val r = random
  51.   distribution._2.find(_._2 > r).get._1
  52. }
  53.  
  54. (0 to 600000).foldLeft(Map.empty[String, Int]) { (freq, _) =>
  55.   val s = sample
  56.   freq.updated(s.label, freq.getOrElse(s.label, 0) + 1)
  57. }
  58.  
  59. // それっぽい分布になる
  60. // res73: scala.collection.immutable.Map[String,Int] = Map(b -> 199610, a -> 100090, c -> 300301)