Given a mapping between items and their required probability of occurrence, generate a million items randomly subject to the given probabilities and compare the target probability of occurrence versus the generated values.

The total of all the probabilities should equal one. (Because floating point arithmetic is involved, this is subject to rounding errors).

aleph   1/5.0
beth    1/6.0
gimel   1/7.0
daleth  1/8.0
he      1/9.0
waw     1/10.0
zayin   1/11.0
heth    1759/27720 # adjusted so that probabilities add to 1
Related task

 Random number generator (device)


 
record Item(value, probability)
 
procedure find_item (items, v)
  sum := 0.0
  every item := !items do {
    if v < sum+item.probability
     then return item.value
     else sum +:= item.probability
  }
  fail # v exceeded 1.0
end
 
# -- helper procedures
 
# count the number of occurrences of i in list l,
# assuming the items are strings
procedure count (l, i)
  result := 0.0
  every x := !l do 
    if x == i then result +:= 1
  return result
end
 
procedure rand_float ()
  return ?1000/1000.0
end
 
# -- test the procedure
procedure main ()
  items := [
    Item("aleph",   1/5.0),
    Item("beth",    1/6.0),
    Item("gimel",   1/7.0),
    Item("daleth",  1/8.0),
    Item("he",      1/9.0),
    Item("waw",     1/10.0),
    Item("zayin",   1/11.0),
    Item("heth",    1759/27720.0)
  ]
 
  # collect a sample of results
  sample := []
  every (1 to 1000000) do push (sample, find_item(items, rand_float ()))
 
  # return comparison of expected vs actual probability
  every item := !items do 
    write (right(item.value, 7) || " " || 
           left(item.probability, 15) || " " || 
           left(count(sample, item.value)/*sample, 6))
end
 