Last active
December 8, 2022 10:45
-
-
Save benmathes/33a10c20796792673676eea4aa8335d3 to your computer and use it in GitHub Desktop.
n-sided dice to m-sided dice
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# rand(n) is a random number 0-(n-1) | |
# e.g. [1,0,0] => 4 | |
def bit_array_to_integer(bit_array) | |
return bit_array.join.to_i(2) | |
end | |
def uniform_bit_from_n_sided_dice(n) | |
roll = rand(n)+1 | |
if n.odd? | |
# e.g. if n = 5, ignore 5 and roll again. | |
# correct but inefficient. | |
while roll == n | |
roll = rand(n)+1 | |
end | |
end | |
return roll[0] | |
end | |
def rand_with_dice(target_sides: 8, source_sides: 6) | |
# roll the source-sided dice once for each bit in | |
# the target distribution. | |
bit_array = [] | |
num_bits_in_target = Math.log(target_sides, 2) | |
for i in 0...num_bits_in_target do | |
bit_array[i] = uniform_bit_from_n_sided_dice(source_sides) | |
end | |
# + 1 to shift from zero-based to one-based | |
return bit_array_to_integer(bit_array) + 1 | |
end | |
# double check the outcomes appear uniform | |
histogram = {} | |
for i in 1...100000 | |
# ... we should really parallelize this histogram generation... | |
target_roll = rand_with_dice(target_sides: 7, source_sides: 5) | |
if histogram[target_roll].nil? | |
histogram[target_roll] = 1 | |
else | |
histogram[target_roll] += 1 | |
end | |
end | |
puts histogram |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Unfortunately doesn't work if the
target_sides
is not a power of 2