Roulette & rand

S

Semih Ozkoseoglu

Hi,

I'm trying to teach my self ruby so i decided to write a simple roulette
that picks a rand number (0 to 36) then decides if its red or black. but
after i've written a version of the code i realized that the code was
biased towards black ( much easier to see over 1 million rolls)

Then to test this I've simplified everything and its still biased
against black. if i take 0 out of the equation and made use (1+rand(25))
the bias disappeared.

Anyway without further annoying you here is the code. If you spin it for
over a million you can easily see the bias (i tried up to 1000000000).

Thanks for any help. I know it's not a life or death situation but for
the life of me I just want to know why is this happening.

THE CODE:

# ARRAYS =======================

black = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33,
35]
red = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34,
36]
zero = [0]

# VARIABLES ===================

bl = 0
rd = 0
zr = 0

# # OF ROLLS ==================

puts 'How many rolls to simulate'
number_of_rolls = gets.chomp.to_i

# THE LOOP ====================

while number_of_rolls > 0


number = rand(36)

if
black.include?(number)
bl +=1
elsif
red.include?(number)
rd +=1
elsif
zero.include?(number)
zr +=1
end
number_of_rolls -=1
end

puts bl
puts rd
puts zr

Attachments:
http://www.ruby-forum.com/attachment/4066/working.rb
 
J

John W Higgins

[Note: parts of this message were removed to make it a legal post.]

Evening Semih,

Hi,

I'm trying to teach my self ruby so i decided to write a simple roulette
that picks a rand number (0 to 36) then decides if its red or black. but
after i've written a version of the code i realized that the code was
biased towards black ( much easier to see over 1 million rolls)

Then to test this I've simplified everything and its still biased
against black. if i take 0 out of the equation and made use (1+rand(25))
the bias disappeared.
I think you meant to say that the bias is against red and towards black (as
you did in the first paragraph) because that's both what I got when trying
your code as well as what will make sense.

Rand doesn't return an integer between 0 and x it returns an integer between
0 and x -1 (http://www.ruby-doc.org/core/classes/Kernel.html#M005974). So
you will find rather quickly that changing your code to rand(37) will work
just fine for you and show no bias as well as the sum of all choices will
equal your number of rolls.

When you ran using rand(36) the highest value you could ever had gotten was
35 and therefore you had 18 black choices - 17 red choices and zero. That
would give you more blacks then reds.

John
 
S

Semih Ozkoseoglu

Hi Jon,

Thanks for the reply. You were completely right. I can't believe I
missed such a thing. I changed 36 to 37 and now everything is as it
should be.

Cheers
Semih
 
S

Stefano Crocco

|Hi,
|
|I'm trying to teach my self ruby so i decided to write a simple roulette
|that picks a rand number (0 to 36) then decides if its red or black. but
|after i've written a version of the code i realized that the code was
|biased towards black ( much easier to see over 1 million rolls)
|
|Then to test this I've simplified everything and its still biased
|against black. if i take 0 out of the equation and made use (1+rand(25))
|the bias disappeared.
|
|Anyway without further annoying you here is the code. If you spin it for
|over a million you can easily see the bias (i tried up to 1000000000).
|
|Thanks for any help. I know it's not a life or death situation but for
|the life of me I just want to know why is this happening.
|
|THE CODE:
|
|# ARRAYS =======================
|
|black = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33,
|35]
|red = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34,
|36]
|zero = [0]
|
|# VARIABLES ===================
|
|bl = 0
|rd = 0
|zr = 0
|
|# # OF ROLLS ==================
|
|puts 'How many rolls to simulate'
|number_of_rolls = gets.chomp.to_i
|
|# THE LOOP ====================
|
|while number_of_rolls > 0
|
|
| number = rand(36)
|
| if
| black.include?(number)
| bl +=1
| elsif
| red.include?(number)
| rd +=1
| elsif
| zero.include?(number)
| zr +=1
| end
| number_of_rolls -=1
|end
|
|puts bl
|puts rd
|puts zr

I think the problem comes from the fact that rand(n) returns an integer
between 0 and n-1. In your case, this means that the number 36 will never be
generated, which in turn implies that there are more black numbers (18) than
red (17 since 36 will never be generated). To avoid this, you'll need to
replace rand(36) with rand(37), which generates numbers between 0 and 36. By
the way, you can greatly simplify your code, like this:

colors = {}

[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31,33,35].each do |i|
colors = :black
end
[1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32,34,36].each do |i|
colors = :red
end
colors[0] = :zero

results = {:black => 0, :red => 0, :zero => 0}

puts 'How many rolls to simulate'
number_of_rolls = gets.chomp.to_i

number_of_rolls.times do
number = rand(37)
color = colors[number]
results[color] += 1
end

puts "Black: #{results[:black]}"
puts "Red: #{results[:red]}"
puts "Zero: #{results[:zero]}"

What this code does is the following:
* create a hash (called colors) which associates each number with its color,
represented by a symbol. The hash is filled from arrays containing the black
numbers and the red ones (it could also be filled by hand:
colors[1] = :red
colors[2] = :black
...
* create the hash results which will contain the number of times each color is
choosen. Therefore, the hash contains three entries, :black, :red and :zero,
all set to 0
* let the user choose the number of rolls
* for the number of times chosen by the user, do the following
- generate a random number between 0 and 36
- get the color corresponding to the number. This is done by looking at the
value corresponding to the number in the colors hash
- increase by one the result relative to the chosen color
* displays the result

I hope this helps

Stefano
 
S

Semih Ozkoseoglu

Hi Stefano,

Thanks for taking the time to write such an helpfull reply. I get your
logic and I like its simpilicity. I will try to simplify my own code as
well.

Its always great to learn a few new things.

Thanks again
Semih
 
S

Semih Ozkoseoglu

Hi again Stefano,

I was looking at the code and as I'm quite new to both programming and
Ruby, I can't seem to understand two things. First is the |i| in
[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31,33,35].each
do |i|

and second is the ':' in why not just 'black' for example.
colors = :black


If you can find the time to tell me what do these do to make the code
work it would be much apriciated.

Thanks again
Semih
 
P

Paul Smith

Hi again Stefano,

I was looking at the code and as I'm quite new to both programming and
Ruby, I can't seem to understand two things. First is the |i| in
[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31,33,35].each
do |i|

The |i| is a block parameter. The each method essentially calls the
code in the following block once for each element in the array, so
each in each iteration of the block i will be equal to the current
element of the array.

Try this in IRB

[1,2,3].each {|x| puts x}

and you'll see what I mean.
and second is the ':' in why not just 'black' for example.
=A0 colors =3D :black


If you can find the time to tell me what do these do to make the code
work it would be much apriciated.


:black is a Symbol, not a String. I'm not sure exactly how much
difference it makes, but from what I've heard it's a good habit to get
into. The trick is that the symbol :black is always the exact same
object, no matter where you see it in your program. On the other
hand, you can have 2 strings with the same contents which will be
different objects.

Try this in IRB

a =3D "black"
b =3D "black"
c =3D :black
d =3D :black

puts a.object_id
puts b.object_id
puts c.object_id
puts d.object_id

You'll notice that a and b are different objects, but c and d are the
same object.
Thanks again
Semih



--=20
Paul Smith
http://www.nomadicfun.co.uk

(e-mail address removed)
 
S

Stefano Crocco

|Hi again Stefano,
|
|I was looking at the code and as I'm quite new to both programming and
|Ruby, I can't seem to understand two things. First is the |i| in
|
|> [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31,33,35].each
|> do |i|

I don't know whether you've already read about blocks in ruby. Given your
question, I don't think so but, in case you did, you can skip the first part
of my answer.

One of the most peculiar characteristics of ruby are blocks. As the name says,
they are blocks of code which can be passed to methods and will be called by
those methods at a later time. They can be introduced either with the syntax

do
...
end

or with
{...}

The ... are actually the body of the block, that is the code which will be
executed later. For example, the code

5.times do
puts "Hello"
end

passes a block whose body is

puts "Hello"

to the "times" method of the object 5. The documentation for the times method
says that n.times calls the block n times, that is it executes the contents of
the block n times. In the example above, n is 5, so times will call execute
the body of the block 5 times. The output is then:

Hello
Hello
Hello
Hello
Hello

Now, I can answer your question: what does
[2,4,6].each do |i|
...
end
mean? As you can see, there are a do and an end keyword, so this must be a
block. The difference with the example above is the |i|. At the very beginning
of the block, immediately after the do keyword or the opening brace, a number
of comma-separated variables (just one, in this case) enclosed in a pair of
pipe characters (|) are the arguments passed to the block. Passing arguments
to a block works in a similar way as passing arguments to a method. In the
code above, for example, the each method of class Array is called. According
to the documentation, the each method calls the block for every element of the
array, passing the element itself to the block. This means that, inside the
body of the block, the variable i will contain one of the elements of the
array in turn. For example:

[2,4,6].each do |i|
puts i
end

outputs:
2
4
6

"each" calls the block three times: the first the argument is 2, so the
variable i is set to 2; the second time i is set to 4 and the third time i is
set to 6.

This is only a very short introduction to blocks. For more, you can look at
http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_containers.html (the
section called "Block and Iterators")

|and second is the ':' in why not just 'black' for example.

In ruby, a sequence of letters, number, underscores (and some other
characters) preceeded by a column (for example, :black) is a Symbol. Symbols
are similar to strings. The main differences is that while every time I write
a string literal, for example "hello", I create a different string, with
symbols this doesn't happen: if I write the symbol :hello one hundred times, I
still get the same object every time. If I had written "hello" one hundred
times, I'd have got one hundred strings all containing the word "hello".
Expecially when beginning programming in ruby, it may be difficult to
understand when it's better to use a symbol rather than a string (you can find
a lot of material on this topic searching google for something like "strings
and symbols"). Symbols are often used as hash keys when you know in advance
which keys are allowed. For example, in your program you already know that the
only possible outcomes of a roll are black, red or zero, so you can use a
symbols as keys. A situation in which symbols wouldn't be a good choice is if
you're storing information about people in the hash, using each person's name
as keys. Obviously, in this case you don't know in advance which would be the
keys of the array, so you should use strings instead.

If you know C or C++, symbols are somewhat similar to enums, except that they
don't have a numerical value associated with them.
|
|> colors = :black
|
|If you can find the time to tell me what do these do to make the code
|work it would be much apriciated.


I hope this helps
|Thanks again
|Semih

Stefano
 
S

Semih Ozkoseoglu

Stefano, Paul,

I thank you both for being so helpful to a noob such as myself. I did
read about the Ruby community before but this is much more than I
expected.

The good thing is that I got it. Ruby is an amazing language, it makes
so much sense.

Again thank you both.


Semih
 
S

Semih Ozkoseoglu

Hi again,

I stumbled upon another interesting problem while I was playing with the
code that I mentioned above.

After the simple roulette code sorted (thanks to everyone who has
responded) I tried to write a code where the bet was decided by another
random roll. Suddenly the code started to loose twice it was loosing
before.

Now correct me if I'm wrong but shouldn't I always loose around 1/37 of
the time; no matter how I decide to bet on what color?

I don't know if there is something wrong with my code or with my logic
and I welcome any suggestions. Again I'm sure its not the most important
problem but I'm just curious why this might be happening.

Thanks for reading and here is the code that I put together so far (i
tried to compare only betting red to betting randomly)


colors = {}
[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33,
35].each do |i|
colors = :black
end
[1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36].each
do |i|
colors = :red
end
colors[0] = :zero

bet_rand = 0
bet_red = 0

puts 'How many rolls to simulate'
number_of_rolls = gets.chomp.to_i

number_of_rolls.times do

number_01 = rand(37)
color_01 = colors[number_01]
number_02 = rand(37)
color_02 = colors[number_02]

if color_01 == :red
bet_red += 1
else
bet_red -= 1
end

if color_02 == color_01
bet_rand += 1
else
bet_rand -= 1
end
end

puts bet_rand
puts bet_red
 
P

Paul Smith

Hi again,

I stumbled upon another interesting problem while I was playing with the
code that I mentioned above.

After the simple roulette code sorted (thanks to everyone who has
responded) I tried to write a code where the bet was decided by another
random roll. Suddenly the code started to loose twice it was loosing
before.

Now correct me if I'm wrong but shouldn't I always loose around 1/37 of
the time; no matter how I decide to bet on what color?

I don't know if there is something wrong with my code or with my logic
and I welcome any suggestions. Again I'm sure its not the most important
problem but I'm just curious =A0why this might be happening.

Thanks for reading and here is the code that I put together so far (i
tried to compare only betting red to betting randomly)


colors =3D {}
[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33,
35].each do |i|
=A0colors =3D :black
end
[1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36].each
do |i|
=A0colors =3D :red
end
=A0colors[0] =3D :zero

bet_rand =3D 0
bet_red =3D 0

puts 'How many rolls to simulate'
number_of_rolls =3D gets.chomp.to_i

number_of_rolls.times do

=A0number_01 =3D rand(37)
=A0color_01 =3D colors[number_01]
=A0number_02 =3D rand(37)
=A0color_02 =3D colors[number_02]

=A0if color_01 =3D=3D :red
=A0 =A0bet_red +=3D 1
=A0else
=A0 =A0bet_red -=3D 1
=A0end

=A0if color_02 =3D=3D color_01
=A0 =A0bet_rand +=3D 1
=A0else
=A0 =A0bet_rand -=3D 1
=A0end
end

puts bet_rand
puts bet_red


One problem that I can see is that you're allowing your random betting
strategy to pick 0, rather than red or black, which I don't think is
your intention.

Change
number_02 =3D rand(37)
color_02 =3D colors[number_02]

to

color_02 =3D [:red, :black][rand(2)]

maybe?

--=20
Paul Smith
http://www.nomadicfun.co.uk

(e-mail address removed)
 
A

Aldric Giacomoni

Symbols are a good habit to get into because they always represent a
unique object, the symbol, while strings always create a new object.
irb(main):009:0> 0.object_id
=> 1
irb(main):010:0> 0.object_id
=> 1
irb(main):011:0> "0".object_id
=> 21396750
irb(main):012:0> "0".object_id
=> 21393440

If we're gonna talk about code simplification..

colors = { 0 => :green }
(1..36).each { |num| colors[num] = (num % 2 == 0) ? :black : :red }

But I'm also lazy, and this is actually slower than the way you guys
generate your hash...
 
P

Paul Smith

Symbols are a good habit to get into because they always represent a
unique object, the symbol, while strings always create a new object.
irb(main):009:0> 0.object_id
=> 1
irb(main):010:0> 0.object_id
=> 1
irb(main):011:0> "0".object_id
=> 21396750
irb(main):012:0> "0".object_id
=> 21393440

If we're gonna talk about code simplification..

colors = { 0 => :green }
(1..36).each { |num| colors[num] = (num % 2 == 0) ? :black : :red }

But I'm also lazy, and this is actually slower than the way you guys
generate your hash...

And also different, as the red and black numbers aren't the odd and
even numbers.
 
D

David A. Black

Hi --

Symbols are a good habit to get into because they always represent a
unique object, the symbol, while strings always create a new object.

That's true, but your example:
irb(main):009:0> 0.object_id
=> 1
irb(main):010:0> 0.object_id
=> 1
irb(main):011:0> "0".object_id
=> 21396750
irb(main):012:0> "0".object_id
=> 21393440

doesn't demonstrate it; you don't have any symbols :)

irb(main):001:0> :x.object_id
=> 158738
irb(main):002:0> :x.object_id
=> 158738


David
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

Hi again,

I stumbled upon another interesting problem while I was playing with the
code that I mentioned above.

After the simple roulette code sorted (thanks to everyone who has
responded) I tried to write a code where the bet was decided by another
random roll. Suddenly the code started to loose twice it was loosing
before.

Now correct me if I'm wrong but shouldn't I always loose around 1/37 of
the time; no matter how I decide to bet on what color?

I don't know if there is something wrong with my code or with my logic
and I welcome any suggestions. Again I'm sure its not the most important
problem but I'm just curious why this might be happening.

Thanks for reading and here is the code that I put together so far (i
tried to compare only betting red to betting randomly)


colors = {}
[2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33,
35].each do |i|
colors = :black
end
[1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36].each
do |i|
colors = :red
end
colors[0] = :zero

bet_rand = 0
bet_red = 0

puts 'How many rolls to simulate'
number_of_rolls = gets.chomp.to_i

number_of_rolls.times do

number_01 = rand(37)
color_01 = colors[number_01]
number_02 = rand(37)
color_02 = colors[number_02]

if color_01 == :red
bet_red += 1
else
bet_red -= 1
end

if color_02 == color_01
bet_rand += 1
else
bet_rand -= 1
end
end

puts bet_rand
puts bet_red

Hi, it is giving me the output that I would expect, here is a image showing
how I calculated it, and I ran the program 3 times with results very similar
to what I calculated they should be.
http://img132.imageshack.us/img132/8939/roulette.png
 
S

Semih Ozkoseoglu

One problem that I can see is that you're allowing your random betting
strategy to pick 0, rather than red or black, which I don't think is
your intention.

Change
number_02 = rand(37)
color_02 = colors[number_02]

to

color_02 = [:red, :black][rand(2)]

maybe?

Hi Paul,

I'll have a look at this issue sometime today and will write an update
if it changes anything.

Thank you.

And Josh,
Hi, it is giving me the output that I would expect, here is a image
showing
how I calculated it, and I ran the program 3 times with results very
similar
to what I calculated they should be.
http://img132.imageshack.us/img132/8939/roulette.png

I get the exact same results with you but what I dont understand is why
you think that the results are normal. I dont understand why it looses
twice as much when you bet randomly (if its not the problem Paul
mentioned above). It would be great if you can tell me how you
calculated what the results should be.

Thanks.
Semih
 
J

Josh Cheek

[Note: parts of this message were removed to make it a legal post.]

And Josh,


I get the exact same results with you but what I dont understand is why
you think that the results are normal. I dont understand why it looses
twice as much when you bet randomly (if its not the problem Paul
mentioned above). It would be great if you can tell me how you
calculated what the results should be.

Thanks.
Semih
Here is the formatted explanation:
http://img38.imageshack.us/img38/8939/roulette.png


And for completeness sake, here is a the unformatted explanation:

Okay, so you are adding 1 for every win (w), and subtracting one for every
loss (l), which gives n*w-n*l , which can be simplified to n(w-l) So for a
pair of win and loss, at some given number of attempts, n, we get the
formula.
[math]f(w,l) = n(w-l)[/math]

You want to know why it's value is approximately twice as large, so let's
compare the two functions by dividing them. We will calculate f for bet_rand
and bet_red, and divide them by eachother.

First we need to find the likelihood of winning and losing, our w and l, for
bet_rand and bet_red.

bet_rand compares color_01 and color_02, each of which are randomly selected
from values 0 through 36 (thirty seven possible values). So there is a 1 in
37 chance of color_01 being zero, and for that case, there is a 1 in 37
chance of color_02 being zero. And there is an 18 in 37 chance of color_01
being red, and a 18 in 37 chance of color_02 being red. And there is an 18
in 37 chance of color_01 being black, and a 18 in 37 chance of color_02
being black.

So this gives us [math]\frac{18}{37} * \frac{18}{37} + \frac{18}{37} *
\frac{18}{37} + \frac{1}{37} * \frac{1}{37}[/math]

Which comes out to [math]\frac{649}{1369}[/math]

And the likelihood of losing is l = 1 - w = [math]\frac{720}{1369}[/math]


Now, for bet_red, color_01 will always be red. So there is a 0 in 37 chance
of color_01 being zero, and for that case, there is a 1 in 37 chance of
color_02 being zero. And there is an 37 in 37 chance of color_01 being red
(because it is manually set to red), and a 18 in 37 chance of color_02 being
red. And there is an 0 in 37 chance of color_01 being black, and a 18 in 37
chance of color_02 being black.

So this gives us [math]\frac{37}{37} * \frac{18}{37} + \frac{0}{37} *
\frac{18}{37} + \frac{0}{37} * \frac{1}{37}[/math]

Which comes out to [math]\frac{18}{37}[/math]

And the likelihood of losing is l = 1 - w = [math]\frac{19}{37}[/math]



So now we have our probabilities to feed the function.

Now, we need to find a meaningful way to compare them. What we will do is
compare their values for some given n, we noticed that bet_rand seemed to
grow about twice as fast as bet_red. So we will divide bet_rand's limit as n
approaches infinity by bet_red's, and see if it comes out to about 2. This
gives us

Our formula
[math]d(w,l) =
\frac{f(w_{bet\_rand},l_{bet\_rand})}{f(w_{bet\_rand},l_{bet\_rand})}[/math]

Fill in the values.
[math]=
\frac{f(\frac{649}{1369},\frac{720}{1369})}{f(\frac{18}{37},\frac{19}{37})}[/math]

Substitute the value of f(w,l)
[math]=
\frac{n(\frac{649}{1369}-\frac{720}{1369})}{n(\frac{18}{37}-\frac{19}{37})}[/math]

At this point, we can see that the value of n is irrelevant, as it cancels
itself out.

[math]=
\frac{(\frac{649}{1369}-\frac{720}{1369})}{(\frac{18}{37}-\frac{19}{37})}[/math]

And simplifying, we get.

[math]= \frac{71}{37}[/math]

[math]\approx 1.91891891891892[/math]

So we have shown that we can expect bet_rand to grow (in a negative
direction) about 1.92 times quicker than bet_red.
 
S

Semih Ozkoseoglu

Hi Josh,

Thanks for taking the time. I might need to read a few more times before
I make sense of your whole solution but I think I understand your point.

Thanks again, its much appreciated.

Semih
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top