(11C) Roll "Four" Dice at Random - Printable Version +- HP Forums (https://www.hpmuseum.org/forum) +-- Forum: HP Software Libraries (/forum-10.html) +--- Forum: General Software Library (/forum-13.html) +--- Thread: (11C) Roll "Four" Dice at Random (/thread-11594.html) |
(11C) Roll "Four" Dice at Random - Gamo - 10-13-2018 03:32 AM Roll 4 dice at random program without using any store registers. Procedure: f [USER] FIX 0 [D] display face 1st dice --> 2nd dice --> 3th dice --> 4th dice and display Total Code:
Gamo RE: (11C) Roll "Four" Dice at Random - Gamo - 10-13-2018 10:21 AM This version used [LBL] D to identify both the beginning of the program and subroutine within the program. So I adapted this program from the "Subroutines Section" on Page 125 of the HP-11C Owner's Handbook. In the handbook state that *While it is generally best to avoid the use of identical labels to reduce the possibility of confusion or programming error, the following program illustrates one way identical labels might be used, if necessary. Procedure: f [USER] FIX 0 [D] display face 1st Dice --> 2nd --> 3th --> 4th and display Total Program: Roll 4 Dice at Random Code:
Gamo RE: (11C) Roll "Four" Dice at Random - Valentin Albillo - 10-13-2018 09:43 PM (10-13-2018 10:21 AM)Gamo Wrote: Program: Roll 4 Dice at Random You can delete the 3 steps I highlighted in red in your code above, the first two because the second LBL D is right after them so merely falling through will achieve the same effect, and the third one because addition ("'+") is conmutative so no need to swap the two numbers being added. V. . RE: (11C) Roll "Four" Dice at Random - Gamo - 10-14-2018 03:48 AM Thanks Valentin Now updated. Gamo RE: (11C) Roll "Four" Dice at Random - Gamo - 10-14-2018 05:37 AM This version cheat a bit by using Direct Exchange Storage Register as a Counter. Code:
Gamo RE: (11C) Roll "Four" Dice at Random - Dieter - 10-14-2018 09:55 PM (10-14-2018 05:37 AM)Gamo Wrote: This version cheat a bit This will only work if register I happens to be zero on program start. Otherwise its value is added to the result. Try it: 777 STO I, then run the program. Also the RCL I and R↑ are no required. Just do it as simple as can be: Code: LBL D Dieter RE: (11C) Roll "Four" Dice at Random - Thomas Klemm - 10-15-2018 07:48 AM (10-14-2018 09:55 PM)Dieter Wrote: Also the RCL I and R↑ are no required. Just do it as simple as can be: If only the sum of the dice is needed we can follow your suggestion from an older post: (05-02-2018 08:03 PM)Dieter Wrote: I just noticed you can save even two more steps if you remove both the CLX and the RCL+1. ;-) Code: LBL D However if you want to use RAN# only once as suggested by (05-02-2018 05:06 AM)Joe Horn Wrote: THE QUESTION: Is there a direct way to return the sum of a roll of N dice without generating N random numbers and adding them together? … you can use this translation of my program for the HP-42S: Code: 001▸LBL D Just be aware that you have to enter the number of dice (here 4) prior to running the program: 4 GSB D Cheers Thomas RE: (11C) Roll "Four" Dice at Random - Albert Chan - 10-15-2018 04:29 PM If tried to pull multiple dice rolls from a single RAN#, the bias might be too high. For example, my Casio RAN# can produce between 0.000 to 0.999 (hopefully, unbiased) For 1 dice roll, dice distribution = 167 + 167 + 166 + 167 + 167 + 166 (3 or 6 is less likely) Ideally, we wanted even distribution, but 167/166 = 1.006 may be good enough. For 3 dice rolls, dice distribution = 80*4 + 136*5. 5/4 = 1.25 is unacceptably bad. To produce unbiased multiple dice roll, remove random below a threshold. For my casio, remove RAN# below 0.136 should do it. >>> total = 1000 # Casio RAN# 0.000 to 0.999 >>> dice3 = 6**3 # treble dice rolls >>> unbiased = [ i % dice3 for i in range(total % dice3, total) ] >>> [ unbiased.count(i) for i in range(dice3) ] [4, 4, 4, 4, 4 ... ] RE: (11C) Roll "Four" Dice at Random - Thomas Klemm - 10-15-2018 06:33 PM (10-15-2018 04:29 PM)Albert Chan Wrote: For 3 dice rolls, dice distribution = 80*4 + 136*5. 5/4 = 1.25 is unacceptably bad. How did you come up with this distribution? Because I get the following result: >>> dice_dist(1000, 1) {0: 167, 1: 167, 2: 166, 3: 167, 4: 167, 5: 166} >>> dice_dist(1000, 2) {0: 335, 1: 333, 2: 332, 3: 335, 4: 333, 5: 332} >>> dice_dist(1000, 3) {0: 503, 1: 501, 2: 496, 3: 503, 4: 501, 5: 496} While this isn't an exact equal distribution I wouldn't say it's biased. However when we roll more dice the imbalance increases: >>> dice_dist(1000, 4) {0: 671, 1: 669, 2: 664, 3: 671, 4: 669, 5: 656} >>> dice_dist(1000, 5) {0: 839, 1: 837, 2: 832, 3: 839, 4: 837, 5: 816} >>> dice_dist(1000, 6) {0: 1007, 1: 1005, 2: 1000, 3: 1007, 4: 1005, 5: 976} This is not a big surprise. There are now gaps between consecutive numbers and thus some of the values aren't hit as last digit. Thus as a rule of thumb we should use it only if \(6^k < n\). Therefore \(6^3 = 216 < 1000\) is still okay while \(6^4 = 1296 > 1000\) starts getting problematic. This is the Python function I used to calculate the distribution of the dice: Code: def base6(n, k): Quote:To produce unbiased multiple dice roll, remove random below a threshold. That means 0 (i.e. [1, 1, 1]) can never happen? How is that not biased? Kind regards Thomas RE: (11C) Roll "Four" Dice at Random - Albert Chan - 10-16-2018 12:17 AM (10-15-2018 06:33 PM)Thomas Klemm Wrote:(10-15-2018 04:29 PM)Albert Chan Wrote: For 3 dice rolls, dice distribution = 80*4 + 136*5. 5/4 = 1.25 is unacceptably bad. My mistake. I was assuming a dice with 216 faces. When the numbers are split back into 3 dice rolls, the distribution is not as bad. 1000 = 216 * 4 + 136 = (216-136) * 4 + 136*5 = 80*4 + 136*5 Doing sum of 3 dice rolls in Mathematica (again, assume RAN# = 0.000 to 0.999): Code: dice3[n_] := 3 + Plus @@ IntegerDigits[Mod[n, 216], 6] ratio = {1.08, 1.08, 1.08, 1.08, 1.07, 1.05, 1.04, 1.03, 1., 0.98, 0.96, 0.92, 0.89, 0.86, 0.86, 0.86} Biased distribution is skew to the small side, as expected. Also, roll sum of 16,17,18 is much less likely ... So, bet small Quote:That means 0 (i.e. [1, 1, 1]) can never happen? To get random integers from RAN#, I do not use INT(216 RAN#); I use (1000 RAN#) % 216 instead. If generated random range is divisible by 216, all are equally likely. That was the reason to drop 1000 % 216 = 136 small cases. Had I done above biased simulation with INT(216 RAN#), distribution is better (relative to unbiased) It seems INT(...) produce enough randomness to compensate ... ratio = {1.08, 1.08, 0.97, 0.95, 1.07, 0.99, 0.97, 1.03, 1.02, 0.97, 1.00, 1.05, 0.93, 0.97, 1.08, 0.86} RE: (11C) Roll "Four" Dice at Random - Thomas Klemm - 10-16-2018 08:37 AM (10-15-2018 07:48 AM)Thomas Klemm Wrote: However if you want to use RAN# only once (…) you can use this translation of my program for the HP-42SIt turns out that multiplying the random number by 64 and then translating the integer part to base 6 is the same as multiplying it continuously by 6, chopping off the integer part and continue with the remainder. Thus just forget about that program and use this instead: Code: 001▸LBL D But then it's slightly longer and a bit biased so rather don't use it at all. Cheers Thomas RE: (11C) Roll "Four" Dice at Random - Albert Chan - 10-16-2018 04:20 PM (10-15-2018 06:33 PM)Thomas Klemm Wrote: >>> dice_dist(1000, 1) I noticed that for decimal random numbers, (i.e n = 10^k, k positive), dice of 3 and 6 is biased down. (assumed generated dice = INT(6 RAN#) + 1, so below 0 meant dice face of 1) >>> dice_dist(10000, 1) {0: 1667, 1: 1667, 2: 1666, 3: 1667, 4: 1667, 5: 1666} >>> dice_dist(100000, 1) {0: 16667, 1: 16667, 2: 16666, 3: 16667, 4: 16667, 5: 16666} >>> dice_dist(1000000, 1) {0: 166667, 1: 166667, 2: 166666, 3: 166667, 4: 166667, 5: 166666} Is this always true ? (10-16-2018 08:37 AM)Thomas Klemm Wrote: It turns out that multiplying the random number by 64 and then translating the integer part to base 6 is the same as Comparing against unbiased distribution, I was unable to measure a bias difference. This is my reference unbiased distribution (first number for sum of 4, last for 24) unbiased = [ 1 4 10 20 35 56 80 104 125 140 146 140 125 104 80 56 35 20 10 4 1 ] this pattern look familiar ... Update: above match coefficient of expanded (x^5 + x^4 + x^3 + x^2 + x + 1)^4 RE: (11C) Roll "Four" Dice at Random - Albert Chan - 10-16-2018 09:17 PM Prove: For RAN# = 0, 1/10^n, 2/10^n, ... (10^n-1)/10^n, evenly distributed, and Dice = INT(6 RAN#) + 1, then dice face 3,6 will appear slightly less often. 10^n - 1 sum of digits = 0, thus divisible by 9, thus divisible by 3 10^n - 1 is odd => 10^n - 1 (mod 6) = 3, so 10^n = 6 k + 4 = 6(k + 2/3), for some integer k Below, use Python definition of range(a,b), i.e. a <= integer value < b: Dice face 1: range(0, k+2/3) = range(0, k+1), total k+1 cases Dice face 2: range(k+1, 2k+4/3) = range(k+1, 2k+2), total k+1 cases Dice face 3: range(2k+2, 3k+6/3) = range(2k+2, 3k+2), total k cases Dice face 4: range(3k+2, 4k+8/3) = range(3k+2, 4k+3), total k+1 cases Dice face 5: range(4k+3, 5k+10/3) = range(4k+3, 5k+4), total k+1 cases Dice face 6: range(5k+4, 6k+12/3) = range(5k+4, 6k+4), total k cases QED Edit: above assumed calculation had enough precision to avoid rounding issue. If calculation is also carried to n digits precision, dice face 2,4 will appear less often. Upper range limit reduced a bit due to possible half-round-up Dice face 1: range(0, k+2/3-0.5/6) = range(0, k+1), total k+1 cases Dice face 2: range(k+1, 2k+4/3-5/6) = range(k+1, 2k+1), total k cases Dice face 3: range(2k+1, 3k+6/3-5/6) = range(2k+1, 3k+2), total k+1 cases Dice face 4: range(3k+2, 4k+8/3-5/6) = range(3k+2, 4k+2), total k cases Dice face 5: range(4k+2, 5k+10/3-5/6) = range(4k+2, 5k+3), total k+1 cases Dice face 6: range(5k+3, 6k+12/3-5/6) = range(5k+3, 6k+4), total k+1 cases Example, k=166, (2k+1)/(6k+4) = 0.333, 0.333 * 6 = 1.998, rounded-up to 2.00 (dice face 3) |