1. Gaussian Distribution Using Dice

What is the formula for calculating the odds of a number appearing
from a set of dice? I'm wanting to plot some bell curve graphs of this.
I have Googled and searched the forum/archive and nothing I can understand.

-=ck
"Programming in a state of EUPHORIA."
http://www.cklester.com/euphoria/

new topic     » topic index » view message » categorize

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/

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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/

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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/

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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

new topic     » goto parent     » topic index » view message » categorize

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. blink
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? blink

>> 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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu