2. Re: Gaussian Distribution Using Dice
This looks good, but, again, I don't understand the last math part...
http://mathforum.org/library/drmath/view/52207.html
I'd just like a FAST function like this:
aNumber = 13 -- what's the odds of the sum of 13
sides = 6 -- appearing when 6-sided dice
rolls = 4 -- are rolled 4 times and added together?
xFromY = instances( aNumber, sides, rolls )
Right now, I'm using a recursive algorithm, as follows:
-- start of code
-- code generated by Win32Lib IDE v0.18.20
include Win32Lib.ew
without warning
--------------------------------------------------------------------------------
-- Window Window1
constant Window1 = createEx( Window, "Window1", 0, Default, Default, 357, 300,
0, 0 )
constant statBar = createEx( StatusBar, "StatusBar8", Window1, 0, 0, 0, 0, 0, 0
)
constant txt_Rolls = createEx( EditText, "3", Window1, 52, 12, 48, 20, 0, 0 )
constant txt_Faces = createEx( EditText, "6", Window1, 52, 36, 48, 20, 0, 0 )
constant LText4 = createEx( LText, "Faces", Window1, 12, 40, 40, 20, 0, 0 )
constant LText5 = createEx( LText, "Rolls", Window1, 12, 16, 36, 20, 0, 0 )
constant LText6 = createEx( LText, "Distribution", Window1, 12, 72, 68, 20, 0, 0
)
constant pix_Graph = createEx( Pixmap, "pix_Graph", Window1, 216, 8, 100, 28, 0,
0 )
sequence IDEFlags
IDEFlags = classDefaults( Window, { {1, {WS_SYSMENU}},{2, {0}} } )
constant CWindow14 = createEx( Window, "CWindow14", Window1, 8, 92, 340, 160,
or_all({WS_CHILD, WS_CLIPSIBLINGS, WS_BORDER}), 0 )
openWindow(CWindow14, Normal)
moveZOrder( CWindow14, HWND_TOP)
---------------------------------------------------------
--------------------------------------------------------------------------------
include xcontrols.ew
include get.e
object junk
sequence rect, origin
integer x, y, width, height, pixX, pixY
constant
GMID = xControl( Geometry, "", Window1, 0, 0, 0, 0, 0, 0 ),
GMIDc = xControl( Geometry, "", CWindow14, 0, 0, 0, 0, 0, 0 )
manage( GMID, CWindow14, {0.0, 0}, {0, 90}, {1.0, 00}, {1.0 , 0} )
manage( GMIDc, pix_Graph, {0.0, 0}, {0.0, 0}, {1.0, 0.0}, {1.0 , 0.0} )
rect = getCtlSize(CWindow14)
width = rect[1]
height = rect[2]
setCtlSize( pix_Graph, width, height )
setPenColor( pix_Graph, Black )
function sum(sequence s)
integer result
result = 0
for t=1 to length(s) do
result += s[t]
end for
return result
end function
function increment(sequence face, integer which, integer max)
face[which] += 1
if face[which] > max then
if which > 1 then
face[which] = 1
face = increment(face,which-1,max)
end if
end if
return face
end function
function getMaxIndex(sequence s)
atom result, max
max = -999999
result = 0
for t=1 to length(s) do
if s[t] > max then
max = s[t]
result = t
end if
end for
return result
end function
function getMax(sequence s)
atom max
max = -999999
for t=1 to length(s) do
if s[t] > max then
max = s[t]
end if
end for
return max
end function
procedure plotGraph()
integer min, max, range, result, sides, rolls, toOne, thickness
sequence faces, results, dice, plotBase, plotPoint
atom scale
rect = getCtlSize(CWindow14)
width = rect[1]
height = rect[2]
origin = { 1 , height-1 }
-- get values
sides = getNumber(txt_Faces)
rolls = getNumber(txt_Rolls)
if sides > 0 and rolls > 0 and rolls <= 3 then
min = rolls
max = min * sides
range = max - min + 1
toOne = rolls - 1
thickness = floor(width / range)
-- plot graph
dice = repeat(1,rolls)
results = repeat(0,range)
while dice[1] != ( sides + 1 ) do
-- for 3d6, starts with {1,1,1}
result = sum(dice)
results[result-toOne]+=1
dice = increment(dice,rolls,sides)
end while
scale = height / getMax(results)
--plot the results
clearWindow(pix_Graph)
clearWindow(CWindow14)
for t=1 to length(results) do
plotBase = origin + {(t-1) * thickness,0}
plotPoint = origin + { plotBase[1]+thickness, floor(-results[t]*scale) }
if t/2 = floor(t/2) then
setPenColor(pix_Graph,Blue)
else
setPenColor(pix_Graph,Black)
end if
drawRectangle(pix_Graph,w32True,plotBase[1],plotBase[2],plotPoint[1],plotPoint[2])
copyBlt(CWindow14, 1, 1, pix_Graph )
end for
setText(statBar, sprintf("%d,%d",origin))
end if
end procedure
--------------------------------------------------------------------------------
procedure Window1_onPaint (integer self, integer event, sequence params)--params
is ( int x1, int y1, int x2, int y2 )
plotGraph()
end procedure
setHandler( Window1, w32HPaint, routine_id("Window1_onPaint"))
--------------------------------------------------------------------------------
procedure Window1_onActivate (integer self, integer event, sequence
params)--params is ()
plotGraph()
end procedure
setHandler( Window1, w32HActivate, routine_id("Window1_onActivate"))
--------------------------------------------------------------------------------
procedure txt_Rolls_onChange (integer self, integer event, sequence
params)--params is ()
plotGraph()
end procedure
setHandler( txt_Rolls, w32HChange, routine_id("txt_Rolls_onChange"))
--------------------------------------------------------------------------------
procedure txt_Faces_onChange (integer self, integer event, sequence
params)--params is ()
plotGraph()
end procedure
setHandler( txt_Faces, w32HChange, routine_id("txt_Faces_onChange"))
--------------------------------------------------------------------------------
procedure CWindow14_onResize (integer self, integer event, sequence
params)--params is ( int style, int cx, int cy )
plotGraph()
end procedure
setHandler( CWindow14, w32HResize, routine_id("CWindow14_onResize"))
WinMain( Window1,Normal )
--end of code
-=ck
"Programming in a state of EUPHORIA."
http://www.cklester.com/euphoria/
3. Re: Gaussian Distribution Using Dice
ck,
Here is my solution but it doesn't do any graffing.
I think it is mathematically correct but it could be wrong.
I just wrote it real quick. It prints up something that
looks right to me.
include get.e
function sum( sequence s )
atom a
a = 0
for i = 1 to length( s ) do
a+= s[i]
end for
return a
end function
constant NumOfDice = 3
constant NumOfSides = 6
constant MaximumRoll = NumOfDice * NumOfSides
sequence chances, dice
chances = repeat( 0, MaximumRoll )
dice = repeat( 1, NumOfDice )
integer roll
for d = 1 to power( NumOfSides, NumOfDice ) do
chances[sum(dice)] += 1
dice[1]+=1
for i = 1 to NumOfDice -1 do
if dice[i] > NumOfSides then
dice[i] = 1
dice[i+1] += 1
end if
end for
end for
printf( 1, "The distobution of %d %d sided dice rolls:\n",
{NumOfDice,NumOfSides} )
puts( 1, "Value\tChance\n" )
for i = 1 to length( chances ) do
printf(1, "%d\t%d\n", i&chances[i] )
end for
if wait_key() then end if
Below lies the signature of Lewis Townsend
Lewy T
4. Re: Gaussian Distribution Using Dice
Lewis Townsend wrote:
>
> ck,
>
> Here is my solution but it doesn't do any graffing.
> I think it is mathematically correct but it could be wrong.
> I just wrote it real quick. It prints up something that
> looks right to me.
Well, it's a billion times faster than my recursive counting
version. Zowie! Thanks LewyT! :)
-=ck
"Programming in a state of EUPHORIA."
http://www.cklester.com/euphoria/
5. Re: Gaussian Distribution Using Dice
cklester wrote:
> This looks good, but, again, I don't understand the last math part...
>
> http://mathforum.org/library/drmath/view/52207.html
This is not a Gaussian Distribution, BTW. A Gaussian Distribution is a
continuous distribution, whereas this is a discrete distribution.
However, the probabilities of sums on multiple dice *approach* a
Gaussian distribution as the number of dice is increased.
> I'd just like a FAST function like this:
>
> aNumber = 13 -- what's the odds of the sum of 13
> sides = 6 -- appearing when 6-sided dice
> rolls = 4 -- are rolled 4 times and added together?
>
> xFromY = instances( aNumber, sides, rolls )
[big snip]
On the URL mentioned above, the formula published 1937 by Uspensky is
provided. The formula uses the Binomial Coefficient (named C() there),
so we first need a function to calculate this. The Binomial Coefficient
is of fundamental meaning for combinatorial calculations, so it's
useful to have that function anyway.
global type nonnegative_int (object x)
if integer(x) then
return x >= 0
end if
return 0
end type
global type positive_int (object x)
if integer(x) then
return x > 0
end if
return 0
end type
global function binomial (integer n, nonnegative_int k)
-- Binomial Coefficient ("n choose k"):
-- Number of (unordered) subsets of k elements from a set of n elements.
-- in : k: nonnegative integer
-- n: integer >= k
-- out: positive integer (not including 0)
atom ret
integer start
if n < k then
return -1 -- Illegal function call
end if
start = n - k
if k > start then -- swap k,start (so k is max.=floor(n/2))
start = k
k = n - k
end if
ret = 1
for i = 1 to k do
start += 1
ret = ret*start/i
end for
return ret
end function
global function ways_to_roll_given_sum (positive_int x, positive_int n, integer
s)
-- in : x: number of sides of each die
-- n: number of dice
-- s: given sum
-- out: number of different ways to roll given sum with given dice
integer ret
ret = 0
for k = 0 to floor((s-n)/x) do
ret += power(-1,k) * binomial(n,k) * binomial(s-x*k-1,n-1)
end for
return ret
end function
-- Demo
integer Sides, Dice, Sum, NumberOfWays
atom Probability
Sides = 6
Dice = 4
Sum = 13
NumberOfWays = ways_to_roll_given_sum(Sides,Dice,Sum)
Probability = NumberOfWays / power(Sides,Dice)
printf(1, "Number of ways(%d,%d,%d) = %d\n", {Sides,Dice,Sum,NumberOfWays})
printf(1, "Probability (%d,%d,%d) = %.2f\n", {Sides,Dice,Sum,Probability})
When you want to calculate the number of ways or probabilities for only
a few cases, this code might be faster than the code provided by Lewis.
Please check yourself.
Regards,
Juergen
6. Re: Gaussian Distribution Using Dice
Juergen Luethje wrote:
>
> cklester wrote:
>
> > This looks good, but, again, I don't understand the last math part...
> >
> > <a
> > href="http://mathforum.org/library/drmath/view/52207.html">http://mathforum.org/library/drmath/view/52207.html</a>
>
> This is not a Gaussian Distribution, BTW. A Gaussian Distribution is a
> continuous distribution, whereas this is a discrete distribution.
I'm glad we have geniuses on hand in the Euforum! :)
> However, the probabilities of sums on multiple dice *approach* a
> Gaussian distribution as the number of dice is increased.
Yeah, I knew that. :P
> When you want to calculate the number of ways or probabilities for only
> a few cases, this code might be faster than the code provided by Lewis.
> Please check yourself.
I haven't run any benchmarks on them yet, but your code works great!
Thank you!
-=ck
"Programming in a state of EUPHORIA."
http://www.cklester.com/euphoria/
7. Re: Gaussian Distribution Using Dice
Just 2 small comments (see below).
Lewis Townsend wrote:
> ck,
>
> Here is my solution but it doesn't do any graffing.
> I think it is mathematically correct but it could be wrong.
> I just wrote it real quick. It prints up something that
> looks right to me.
>
> }}}
<eucode>
> include get.e
>
> function sum( sequence s )
> atom a
> a = 0
> for i = 1 to length( s ) do
> a+= s[i]
> end for
> return a
> end function
>
> constant NumOfDice = 3
> constant NumOfSides = 6
>
> constant MaximumRoll = NumOfDice * NumOfSides
>
> sequence chances, dice
> chances = repeat( 0, MaximumRoll )
> dice = repeat( 1, NumOfDice )
>
> integer roll
Local variable roll is not used.
> for d = 1 to power( NumOfSides, NumOfDice ) do
> chances[sum(dice)] += 1
> dice[1]+=1
> for i = 1 to NumOfDice -1 do
> if dice[i] > NumOfSides then
> dice[i] = 1
> dice[i+1] += 1
-- this makes it faster:
else
exit
> end if
> end for
> end for
>
>
> printf( 1, "The distobution of %d %d sided dice rolls:\n",
> {NumOfDice,NumOfSides} )
> puts( 1, "Value\tChance\n" )
> for i = 1 to length( chances ) do
> printf(1, "%d\t%d\n", i&chances[i] )
> end for
> if wait_key() then end if
> </eucode>
{{{
Regards,
Juergen
8. Re: Gaussian Distribution Using Dice
Juergen Luethje wrote:
>
> Just 2 small comments (see below).
>
> Lewis Townsend wrote:
>
> > ck,
> >
> > Here is my solution but it doesn't do any graffing.
> > I think it is mathematically correct but it could be wrong.
> > I just wrote it real quick. It prints up something that
> > looks right to me.
> >
> <font color="#330033">> </font>
> <font color="#330033">> </font><font color="#0000FF">include </font><font
> color="#330033">get.e</font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#0000FF">function </font><font
> color="#330033">sum( </font><font color="#FF00FF">sequence </font><font
> color="#330033">s )</font>
> <font color="#330033">> </font><font color="#FF00FF">atom </font><font
> color="#330033">a</font>
> <font color="#330033">> a = 0</font>
> <font color="#330033">> </font><font color="#0000FF">for </font><font
> color="#330033">i = 1 </font><font color="#0000FF">to </font><font
> color="#FF00FF">length</font><font color="#330033">( s ) </font><font
> color="#0000FF">do</font>
> <font color="#330033">> a+= s[i]</font>
> <font color="#330033">> </font><font color="#0000FF">end for</font>
> <font color="#330033">> </font><font color="#0000FF">return </font><font
> color="#330033">a</font>
> <font color="#330033">> </font><font color="#0000FF">end function</font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#0000FF">constant </font><font
> color="#330033">NumOfDice = 3</font>
> <font color="#330033">> </font><font color="#0000FF">constant </font><font
> color="#330033">NumOfSides = 6</font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#0000FF">constant </font><font
> color="#330033">MaximumRoll = NumOfDice * NumOfSides</font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#FF00FF">sequence </font><font
> color="#330033">chances, dice</font>
> <font color="#330033">> chances = </font><font
> color="#FF00FF">repeat</font><font color="#330033">( 0, MaximumRoll )</font>
> <font color="#330033">> dice = </font><font color="#FF00FF">repeat</font><font
> color="#330033">( 1, NumOfDice )</font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#FF00FF">integer </font><font
> color="#330033">roll</font>
> <font color="#330033"></font>
> <font color="#330033">Local variable roll is </font><font color="#0000FF">not
> </font><font color="#330033">used.</font>
> <font color="#330033"></font>
> <font color="#330033">> </font><font color="#0000FF">for </font><font
> color="#330033">d = 1 </font><font color="#0000FF">to </font><font
> color="#FF00FF">power</font><font color="#330033">( NumOfSides, NumOfDice )
> </font><font color="#0000FF">do</font>
> <font color="#330033">> chances[sum</font><font color="#993333">(</font><font
> color="#330033">dice</font><font color="#993333">)</font><font color="#330033">]
> += 1</font>
> <font color="#330033">> dice[1]+=1</font>
> <font color="#330033">> </font><font color="#0000FF">for </font><font
> color="#330033">i = 1 </font><font color="#0000FF">to </font><font
> color="#330033">NumOfDice -1 </font><font color="#0000FF">do</font>
> <font color="#330033">> </font><font color="#0000FF">if </font><font
> color="#330033">dice[i] > NumOfSides </font><font color="#0000FF">then</font>
> <font color="#330033">> dice[i] = 1</font>
> <font color="#330033">> dice[i+1] += 1</font>
> <font color="#330033"></font>
> <font color="#FF0055"> -- this makes it faster:</font>
> <font color="#0000FF"> else</font>
> <font color="#0000FF"> exit</font>
> <font color="#330033"></font>
> <font color="#330033">> </font><font color="#0000FF">end if</font>
> <font color="#330033">> </font><font color="#0000FF">end for</font>
> <font color="#330033">> </font><font color="#0000FF">end for</font>
> <font color="#330033">></font>
> <font color="#330033">></font>
> <font color="#330033">> </font><font color="#FF00FF">printf</font><font
> color="#330033">( 1, </font><font color="#00A033">"The distobution of %d %d sided
> dice rolls:\n"</font><font color="#330033">, </font><font
> color="#993333">{</font><font color="#330033">NumOfDice,NumOfSides</font><font
> color="#993333">} </font><font color="#330033">)</font>
> <font color="#330033">> </font><font color="#FF00FF">puts</font><font
> color="#330033">( 1, </font><font color="#00A033">"Value\tChance\n" </font><font
> color="#330033">)</font>
> <font color="#330033">> </font><font color="#0000FF">for </font><font
> color="#330033">i = 1 </font><font color="#0000FF">to </font><font
> color="#FF00FF">length</font><font color="#330033">( chances ) </font><font
> color="#0000FF">do</font>
> <font color="#330033">> </font><font color="#FF00FF">printf</font><font
> color="#330033">(1, </font><font color="#00A033">"%d\t%d\n"</font><font
> color="#330033">, i&chances</font><font color="#993333">[</font><font
> color="#330033">i</font><font color="#993333">] </font><font
> color="#330033">)</font>
> <font color="#330033">> </font><font color="#0000FF">end for</font>
> <font color="#330033">> </font><font color="#0000FF">if </font><font
> color="#330033">wait_key() </font><font color="#0000FF">then end if</font>
> <font color="#330033">> </font>
>
> Regards,
> Juergen
>
>
Oh yeah, that roll integer don't need to be there.
I started to use it then decided I needed the dice sequence instead.
Thanks for speeding it up with that exit statement.
I forget about stuff like that sometimes.
Below lies the signature of Lewis Townsend
Lewy T
9. Re: Gaussian Distribution Using Dice
cklester wrote:
> Juergen Luethje wrote:
>>
>> cklester wrote:
>>
>>> This looks good, but, again, I don't understand the last math part...
>>>
>>> http://mathforum.org/library/drmath/view/52207.html
>>
>> This is not a Gaussian Distribution, BTW. A Gaussian Distribution is a
>> continuous distribution, whereas this is a discrete distribution.
>
> I'm glad we have geniuses on hand in the Euforum! :)
Me too.
But that has nothing got to do with the difference between continuous and
discrete probability distributions. This difference is explained in any
statistical textbook on, say, page 23.
>> However, the probabilities of sums on multiple dice *approach* a
>> Gaussian distribution as the number of dice is increased.
>
> Yeah, I knew that. :P
So the only remaining mystery is: Who wrote "Gaussian Distribution"
in the name of this thread. And why?
>> When you want to calculate the number of ways or probabilities for only
>> a few cases, this code might be faster than the code provided by Lewis.
>> Please check yourself.
>
> I haven't run any benchmarks on them yet, but your code works great!
>
> Thank you!
Regards,
Juergen