def von_neuman(seed=Time.now.nsec, sequence=[], vn_size=100) # generates a von_neuman pseudo-random sequence (array) using current date-time in nanoseconds as seed if sequence.size < vn_size y = (seed**2).digits z = y[y.size/2 - seed.digits.size/4, y.size/2 + seed.digits.size/4] new_seed = z.join.to_i von_neuman(new_seed, sequence+z) else sequence end end class Array def head self[0] end def tail self[1..-1] end def first_in_range(range) # returns a new array where the first element of this new array is included in # such range e.g. [0,1,2,3,4,5].first_in_range(3..4) -> [3,4,5] range.include?(self.head) ? self : self.tail.first_in_range(range) end end def roll_dice(rs=[],rolls=1,sides=6,dice=[]) rs = von_neuman if rs.size == 0 # Avoids the odd chance of not finding any 1..6 values in the random sequence by generating it again if rolls > 0 x = rs.first_in_range(1..sides) roll_dice(x.tail,rolls-1,sides,dice.push(x.head)) else dice end end def three_dice(rs=[]) roll_dice(rs,3,6,[]).sum end # --- pseudo tests :) ------------ puts "Generating a Von Neuman pseudo-random series. First 24 elements" puts von_neuman.inspect puts "\n18 dice rolls \n#{roll_dice([],18,6,[])}\n" puts "\n18 3d6\n" 18.times do |x| puts "#{x+1}.- #{three_dice}" end