From ef360a7759aaec7d338e69376e5d0ff7a6533fd2 Mon Sep 17 00:00:00 2001 From: pxi Date: Mon, 11 Dec 2023 21:57:17 +0100 Subject: [PATCH] =?UTF-8?q?=C2=AF\=5F=E2=96=90=20=E2=98=AF=20=EF=B8=BF=20?= =?UTF-8?q?=E2=98=AF=20=E2=96=90=5F/=C2=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 99 ++++++++++++++++++++++++++++++++++++++++++- bin/3d6rl-vs-4d6dl.py | 60 ++++++++++++++++++++++++++ 2 files changed, 157 insertions(+), 2 deletions(-) create mode 100755 bin/3d6rl-vs-4d6dl.py diff --git a/README.md b/README.md index a1b8004..a87bac6 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,98 @@ -# 3d6rl-vs-4d6dl +# 🎲 3d6 Re-roll Lowest 🆚 4d6 Drop Lowest 🎲 + +A python script to generate results on rolling dice implementing a quantum number generator ([qrng.anu.edu](http://qrng.anu.edu.au/)) as source of randomness. + +**Thanks** to [@philvuchetich@bsd.network](https://bsd.network/@philvuchetich) for the help and pointers making this work. + +## How to use this script + +Install the random generator + +````shell +pip3 install quantumrandom +```` + +Run the script + +````shell +./bin/3d6rl-vs-4d6dl.py +```` + +## Method Explanation + +### 4d6DL + +Roll 4 six-sided dice and drop the lowest result. + +- Using only 6 sided dice roll a set of 4 dice. +- Remove the lowest result from the set. +- Add the three remaining dice and note the total sum. + +### 3d6RL + +Roll 3 six-sided dice and re-roll the lowest result. + +- Using only 6 sided dice roll a set of 3 dice. +- Re-roll the lowest dice. +- If the result is higher keep the use this value instead. +- Add the three dice together and note the total sum. + +## Thesis + +The result average for both methods (4d6DL and 3d6RL) should be close, if not the same. And tend towards equality the more the two methods it are tested. + +This script generates results sets using a digital version of the above mentioned methods, ideally the more sets used the closer to zero the difference should be. + +## Results + +The results for 10.000 where 4d6DL rolled 0.20500% more than 3d6RL, using 100.000 3d6rl with 0.02133%, and finally 1.000.000 samples 4d6DL again with 0.01322% difference. + +### Result sample + +``` +$ ./bin/3d6rl-vs-4d6dl.py +3d6 Re-roll Lowest - 1000000 samples +Distribution (result : times) +3 : 776 +4 : 3093 +5 : 7667 +6 : 16344 +7 : 29745 +8 : 47978 +9 : 70516 +10 : 93752 +11 : 114493 +12 : 128574 +13 : 132726 +14 : 122853 +15 : 101249 +16 : 72396 +17 : 41686 +18 : 16152 +67.99701% (12239462 of 18000000). + +4d6 Drop Lowest - 1000000 samples +Distribution (result : times) +3 : 813 +4 : 3181 +5 : 7796 +6 : 16136 +7 : 29519 +8 : 47601 +9 : 70463 +10 : 93906 +11 : 114615 +12 : 128518 +13 : 132829 +14 : 123235 +15 : 101007 +16 : 72473 +17 : 41851 +18 : 16057 +68.01023% (12241841 of 18000000). + +4d6dl rolled more by 0.01322% +``` + + -A python script to generate results on rolling dice implementing a quantum number generator as source of randomness. \ No newline at end of file diff --git a/bin/3d6rl-vs-4d6dl.py b/bin/3d6rl-vs-4d6dl.py new file mode 100755 index 0000000..600918d --- /dev/null +++ b/bin/3d6rl-vs-4d6dl.py @@ -0,0 +1,60 @@ +#! /usr/bin/python3 + +import random +import quantumrandom # pip3 install quantumrandom + +sample = 1000000 +die_min = 1 +die_max = 6 +max_amount = (die_max * 3) * sample +qseed = quantumrandom.get_data(); # get seed from quantum API +quantum_os_rand = random.SystemRandom(qseed[0]) +dist_rl, dist_dl = {}, {} +i, rl_total, dl_total = 0, 0, 0 + +def roll(): + #return random.randint(die_min, die_max) # bad: Pseudo-random + #return random.SystemRandom().randint(die_min, die_max) # better: OS random + return quantum_os_rand.randint(die_min, die_max) # good: OS with Quantum seed + #return quantomrandom.randint(die_min, die_max) # amazing: Slow, try 10 samples max + +def drop_lowest(arr): + arr.remove(min(arr)) + return arr + +def reroll_lowest(arr): + arr.sort() + old_roll = arr.pop(0) + new_roll = roll() + if old_roll <= new_roll: + arr.append(new_roll) + else: + arr.append(old_roll) + return arr + +while i < sample: + rl_set = sum(reroll_lowest([roll(), roll(), roll()])) + rl_total += rl_set + dist_rl[rl_set] = dist_rl.get(rl_set, 0) + 1 + + dl_set = sum(drop_lowest([roll(), roll(), roll(), roll()])) + dl_total += dl_set + dist_dl[dl_set] = dist_dl.get(dl_set, 0) + 1 + i += 1 + +p_rl, p_dl = ((100 / max_amount) * rl_total), ((100 / max_amount) * dl_total) + +print("3d{:d} Re-roll Lowest - {:d} samples\nDistribution (result : times)".format(die_max, sample)) +for attribute, value in dict(sorted(dist_rl.items())).items(): + print('{:d} : {:d}'.format(attribute, value)) +print("{:.5f}% ({:d} of {:d}).\n".format(p_rl, rl_total, max_amount)) + +print("4d{:d} Drop Lowest - {:d} samples\nDistribution (result : times)".format(die_max, sample)) +for attribute, value in dict(sorted(dist_dl.items())).items(): + print('{:d} : {:d}'.format(attribute, value)) +print("{:.5f}% ({:d} of {:d}).\n".format(p_dl, dl_total, max_amount)) + +if rl_total < dl_total: + print("4d{:d}dl rolled more by {:.5f}%".format(die_max, p_dl - p_rl)) +else: + print("3d{:d}rl rolled more by {:.5f}%".format(die_max, p_rl - p_dl))