• (cs) in reply to Sid2K7
Sid2K7:
Oh, you're talking about American Roulette. Not Roulette. Just like American Football isn't usually played with one's foot...

scnr...

Right... because the addition of a "00" spot TOTALLY CHANGES THE GAME.

Euro-twit.

• Person (unregistered) in reply to BentFranklin
BentFranklin:
TRWTF is why anyone would write a program when it can (and should) be solved analytically.

The point is to practice in a programming language you're not that familiar with or to spend some time coding away from the project you might be bogged down in right now. There sure are a bunch of self-righteous whiners around here.

The title is called "Knocking Me Off The Perch". That tells me that we are supposed to write some code to simulate the situation that Alex wrote about to prove why it won't work! We are knocking him off of the idea that he is stuck on because it seems like it should be a sure-fire way to win (if you ignore what you know about probability and are inebriated).

I took some time and played around with the concept in C++ even though I knew there would still be a (APPROXIMATE!!!) 50-50 chance of winning regardless of the streak that was spun on the wheel previously... It was a nice distraction and it cleared my head for a while.

You guys are probably the ones that can't enjoy a movie because you sit there picking apart all the little technical errors that don't matter rather than just sitting back and enjoying the story as a whole.

/rant...

• (cs)

The key to this problem is realizing that the Perch is not a good strategy. On average, in ideal conditions, you'll lose.

Let's look at one particular condition. Let's say a table has 4 blacks in a row. The odds of that happening are 9/19 for each black, so 6561/130321 in total. Now what are the odds of the next chip being black? You might think not much at all, but if you do you've forgotten something: The odds of the last 4 rolls being black is 1, because it already happened! Instead, we look at the odds of getting a red next, and it's 9/19. It's always 9/19. No matter what previous rolls are, they have NO EFFECT on future rolls.

I don't know what the probability of turning \$10 into \$400 is, but it's very low considering that you can lose on the first try by 10/19 and then be broke (assuming that's part of the problem). There also is no limit on the number of times you can bet, so you could go from \$10 to \$20 and back to \$10 for all eternity, before going on a winning streak and getting \$400. So you probably have to find the limit of some equation to get the proper probability that takes this into account.

• Sequence, it's all about the probability of the sequence.... (unregistered) in reply to There is so much WTF in this I don't know where to start
There is so much WTF in this I don't know where to start:
The roulette table has NO MEMORY of the previous sequence of events (black or red). Read this several times till you understand this concept.

Randomness is not the roulette table keeping a tally of all the reds and blacks in sequence and making sure there are the same number of each (ignoring the greens which I'll get to in a minute) or a fair-looking alternation of red and black sequences.

The sequence of random black and red is truly random - 100 black followed by 100 red is JUST AS LIKELY as RED-BLACK-RED-BLACK (repeated forever) or RRRR-BBBB-RRRR-BBBB...or any other combination.

Each subsequent outcome is completely unaffected by the previous colour.

Is that so? Just as likely to get 100 red in a row than RBRBRB? Ok, if you know so much about probability, then let's go to a casino. I'll bet you \$1000 that you won't see 100 red in a row....

Sure a table has no "memory" of the previous rolls, but that doesn't mean the probability of a given sequence is the same. The point is the probability of a sequence of 5 reds is more unlikely than a sequence of 4 reds. It's the sequence probability that you're working with here, not the probability of a single given roll.

• (cs)

<rant> I really enjoy these BYOC contests, all you people complaining about difficulty and or semantics instead of writing code are simply annoying. I've completed several of them, and in cases where the solution was posted, like in knights I came up with my own brute force version. These problems are meant to be fun little games, I'm using them to keep my Python sharp while I spend my days developing in C++. </rant> My version below is in python, I had to tweak it a little to interpret what to do after 5 bets(whether to reset the result counter) and to adjust the termination conditions as well.

import random

def build_wheel(num_red=18,num_black=18,num_green=2):
"""makes an authentic wheel, with the colors in the right place,
though I've only tested it for num_green=1,2 I think this should
work no matter what, as long as num_red==num_black>num_green"""
wheel=[]
total=num_red+num_green+num_black;
green_pos=(num_red+num_black)/num_green;
for i in range(0,total):
if((i%(green_pos+1))==0 and num_green>0):
wheel.append('g')
num_green=num_green-1
else:
if(num_red>=num_black):
wheel.append('r')
num_red=num_red-1
else:
wheel.append('b')
num_black=num_black-1
return wheel

def spin_wheel(wheel):
size=len(wheel)
return wheel[random.randint(0,size-1)]

"""plays the perch betting stratagey, assuming we
reset the table count at 5 of the same color in a row
and that we can play multiple tables at once"""
wheel=build_wheel()
tables=[]
for i in range(0,num_tables):
tables.append(['n',0])
num_bets=0;
while(bank>=min_bet):
#for j in range(0,20):
for table in tables:
return (bank,num_bets)
bet_val=0
bet='n'
if(table[1]==4 and table[0]!='g' and bank>=min_bet):
num_bets=num_bets+1
bet_val=min_bet
bank=bank-bet_val
if(table[0]=='r'):
bet='b'
else:
bet='r'
if(table[1]==5 and table[0]!='g' and (bank>=min_bet*1.5)):
num_bets=num_bets+1
bet_val=min_bet*1.5
bank=bank-bet_val
if(table[0]=='r'):
bet='b'
else:
bet='r'
outcome=spin_wheel(wheel)
if(bet==outcome):
bank=bank+2*bet_val
if(table[0]==outcome):
table[1]=table[1]+1
else:
table[0]=outcome
table[1]=1
# I'm assuming at a run of 5 weather we win or not we reset the roll tracker
if(table[1]>5):
table[0]='n'
table[1]=0
return (bank,num_bets)

print the_perch()

#calculate odds of quiting while ahead for 100 tries
wins=0
for i in range(0,100):
result=the_perch()
if(result[0]>=400):
wins+=1
print "Odds of quiting while ahead: ", wins/100.0
#calculate odds of quiting while ahead for 1000 tries
wins=0
for i in range(0,1000):
result=the_perch()
if(result[0]>=400):
wins+=1
print "Odds of quiting while ahead: ", wins/1000.0

• Hatterson (unregistered) in reply to Sequence, it's all about the probability of the sequence....
Sequence:
There is so much WTF in this I don't know where to start:
The roulette table has NO MEMORY of the previous sequence of events (black or red). Read this several times till you understand this concept.

Randomness is not the roulette table keeping a tally of all the reds and blacks in sequence and making sure there are the same number of each (ignoring the greens which I'll get to in a minute) or a fair-looking alternation of red and black sequences.

The sequence of random black and red is truly random - 100 black followed by 100 red is JUST AS LIKELY as RED-BLACK-RED-BLACK (repeated forever) or RRRR-BBBB-RRRR-BBBB...or any other combination.

Each subsequent outcome is completely unaffected by the previous colour.

Is that so? Just as likely to get 100 red in a row than RBRBRB? Ok, if you know so much about probability, then let's go to a casino. I'll bet you \$1000 that you won't see 100 red in a row....

Sure a table has no "memory" of the previous rolls, but that doesn't mean the probability of a given sequence is the same. The point is the probability of a sequence of 5 reds is more unlikely than a sequence of 4 reds. It's the sequence probability that you're working with here, not the probability of a single given roll.

I really can't decide if this is a troll or not....however to humor you.

TTTT is a 1/16 probability.

TTTTT is a 1/32 probability TTTTH is a 1/32 probability HTHTH is a 1/32 probability THTHT is a 1/32 probability

More generally, all sequences of a given length have the same probability.

• (cs)

It seems that this commenting system hates Prolog. But you, gentle reader, love Prolog. How could you not? Then go here to see a Prolog solution. What's not to love?

Addendum (2009-08-19 13:49): Blast this demonic board! This is what happens when people fail to give Prolog the respect it deserves. The correct Prolog code is [url=http://pastebin.com/mec543ad]here[url].

Let's try posting the code, too!

determine_output(X, black) :-
X < 18,
!.
determine_output(X, red) :-
X < 36,
!.
determine_output(_, green).

roll_table(Table, NewTable) :-
length(Table, Len),
Len < 4,
X is random(38),
determine_output(X, Y),
append(Table, [Y], NewTable).

roll_table([_|Tail], Table) :-
X is random(38),
determine_output(X, Y),
append(Tail, [Y], Table).

roll_tables([], []).
roll_tables(Tail, X),

roll_tables(Tables, NewTables, Rolls, NewRolls) :-
roll_tables(Tables, NewTables),
NewRolls is Rolls + 1.

table_streak([], red).
table_streak([], black).

invert(black, red).
invert(red, black).

streak([], _, _, _) :-
fail.
streak([Table|_], Curr, Bet, Curr) :-
length(Table, X),
X > 3,
table_streak(Table, B),
invert(B, Bet).
streak([_|Tail], TableNum, Bet, Curr) :-
Next is Curr + 1,
streak(Tail, TableNum, Bet, Next).

streak(Table, TableNum, Bet) :-
streak(Table, TableNum, Bet, 0).

output_result(TableNum, Spin, Bet, BetAmount, Roll) :-
write('Roll #'),
write(Roll),
write(' - Bet '),
write(BetAmount),
write(' on '),
write(Bet),
write(', table #'),
T is TableNum + 1,
write(T),
write('.  Outcome is '),
write(Spin),
write('.  ').

result(TableNum, Spin, Spin, BetAmount, BetAmount, Roll) :-
output_result(TableNum, Spin, Spin, BetAmount, Roll),
write('WIN!'),
nl.
result(TableNum, Spin, Bet, BetAmount, WinAmount, Roll) :-
output_result(TableNum, Spin, Bet, BetAmount, Roll),
write('LOSE!'),
nl,
WinAmount is -BetAmount.

stick_around(WinAmount, B, T, R, _, _, B, T, R) :-
WinAmount > 0, !.
stick_around(_, Bankroll, T, R, _, _, Bankroll, T, R) :-
Bankroll < 15, !.
stick_around(_, Bankroll, Tables, Rolls, TableNum, Bet, NewBankroll, NewTables, NewRolls) :-
roll_tables(Tables, NewTables, Rolls, NewRolls),
nth0(TableNum, NewTables, Table),
nth1(4, Table, Spin),
result(TableNum, Spin, Bet, 15, Outcome, NewRolls),
NewBankroll is Bankroll + Outcome.

perch_roll(Bankroll, _, _, Bankroll, NumRolls) :-
Bankroll < 10,
write('Bankroll less than minimum bet.  Bankroll: '),
write(Bankroll),
write('.  Rolls taken: '),
write(NumRolls),
nl.
perch_roll(Bankroll, _, Goal, Bankroll, NumRolls) :-
Bankroll >= Goal,
write('GOAL REACHED!  Bankroll: '),
write(Bankroll),
write('.  Rolls taken: '),
write(NumRolls),
nl.
perch_roll(Bankroll, Tables, Goal, Outcome, Rolls) :-
streak(Tables, TableNum, Bet),
!,
roll_tables(Tables, T, Rolls, R),
nth0(TableNum, T, Table),
nth1(4, Table, Spin),
result(TableNum, Spin, Bet, 10, WinAmount, R),
B is Bankroll + WinAmount,
stick_around(WinAmount, B, T, R, TableNum, Bet, NewBankroll, NewTables, NewRolls),
perch_roll(NewBankroll, NewTables, Goal, Outcome, NewRolls).
perch_roll(Bankroll, Tables, Goal, Outcome, Rolls) :-
roll_tables(Tables, NewTables, Rolls, NewRolls),
perch_roll(Bankroll, NewTables, Goal, Outcome, NewRolls).

perch(StartingBankroll, NumTables, Goal, FinalBankroll) :-
length(Tables, NumTables),
maplist(=([]), Tables),
perch_roll(StartingBankroll, Tables, Goal, FinalBankroll, 0).

• (cs) in reply to Otto
Otto:
Boy Girl Paradox You ask a woman how many children she has and she says two. Then for some strange reason you ask her, "Is at least one a girl?", to which she replies, "Yes".

So what are the odds that she has a girl and a boy?

(to avoid some argument: assume this is a perfect world where the odds of boy or girl conception are 50/50 and that there are no genetic "third sex" possibilities)

Err.. That seems obvious. The odds that she has a boy and girl at the end of the statement is 2/3rds.

Four possibles: BB BG GB GG

The question "Is at least one a girl?" eliminates the first option, leaving three. 2/3 of those are one girl, one boy. Simple.

Note that you also have to assume that the children's genders are independent of each other, which is actually not the case in real-life siblings with the same parents.

Except GB and BG are the same thing. The question isn't concerning itself with the order in which they were born. Now your options are:

BB GG GB/BG (however you want to order it)

So #1 is already eliminated therefore it's 1/2. If the order was important 2/3 would be correct. The question is not asking "What are the odds the younger child is a boy?" which it would have to for your answer to be correct.

• Joe Strazzere (unregistered)

"Perhaps it was the alcohol, or maybe the elation from the first two bets, but the strategy seemed solid"

It was the alchohol. The strategy is as flawed as all others.

• Anonymous (unregistered)

According to some movie I saw once, if you scream really loud, you can make it come up green. And then your boyfriend doesn't die. Or something.

• (cs) in reply to akatherder
akatherder:
What are the odds of flipping a coin 4 times and getting heads every time?
Depends on how your mom feels like.
• Dr_Legacy (unregistered)
\$23,148,855,308,184,500!

thought that number (less the factorial sign) looked familiar, i just got a bill for that amount.

now 23,148,855,308,184,500!, that's a big number!

• Jay (unregistered) in reply to mol1111
mol1111:
ThatsALotOfGravy:
There is so much WTF in this I don't know where to start:
The sequence of random black and red is truly random - 100 black followed by 100 red is JUST AS LIKELY as RED-BLACK-RED-BLACK (repeated forever) or RRRR-BBBB-RRRR-BBBB...or any other combination.

Woah woah woah, slow down. The chance of the combined event of getting black 100 times in a row is EXTREMELY low, on the order of 1 in 2^100 (let's ignore green).

The probability is low, however equal any other combination of the same length.

I believe the original posters points was that, yes, the odds of getting black, say, 10 times in a row are indeed very small -- about 1/2^10 (technically a little less with the greens) -- but they are exactly the same as getting any given random-sounding sequence. i.e. BBBBBBBBBB is small, but exactly the same as BRRBBRBBRR.

• Jay (unregistered)

I saw an interview with the owner of a casino once in which he said, "If you have a lot of money to bet and you're feeling lucky, we'll meet you at the airport. If you have a system, we'll send a plane for you."

My daughter works in a hotel attached to a casino, and she once told me that there are a lot of people who come and play 2 slots machines simultaneously, put money in one, pull the handle, and while it's spinning put money in another and start it, then come back to the first. "That way," she said, "they can lose their money twice as fast." She also has many amusing stories about idiots, like the guy who came to the front desk one morning to ask if someone could give him a ride home to Utah, because the previous night he had gambled away his car. As a nervous father I was worried about her getting a job at a casino, but in reality it probably keeps her away from gambling: she sees how the only people making money at this are the casino owners.

• Mez (unregistered)

Ok, well, seeing as I used to work in a casino, and saw this on a regular basis...

Here's my PHP code.

http://files.sourceguru.net/perch.txt

(captcha = acsi ... a limited version of ascii?)

• *groaner* (unregistered)

I love how these BYOCs immediately turn into a google-off, instead of a code-off.

What kind of narcissistic, self-inflated egotist would grab a paragraph or quote off of (ffs!) wikipedia(‽) and claim it as their own? Apparently the kind that makes up a rather large percentage of this forum's members.

Meanwhile, Alex, come clean. We all know this was inspired by the reddit post about the spammer's variant of the Martingale "strategy" three days ago. Still, good show on the BYOC challenges. The troll potential is through the freaking ROOF!

grin

• mb (unregistered)

A drunk man normally has an even chance to take a 1 foot step to the left or a step to the right (no, he's not doing the Timewarp). Because we are sadists, we place a drunkard 1 foot to the right of a cliff. Also, the ground is slightly tilted, which means this poor besotted fellow is slightly (3%) more likely to take a step to the right. However, if he manages to wander 400 feet uphill, there is a kindly social worker who will take him away to rehab.

What are the chances that our drunk ends up dead at the bottom of a cliff?

• Anthony Aziz (unregistered) in reply to Code Dependent

Not at Caesor's Windsor. I lost \$120 there last week and then they offered me something to drink ;/

• (cs) in reply to webhamster
webhamster:
Except GB and BG are the same thing. The question isn't concerning itself with the order in which they were born. Now your options are:

BB GG GB/BG (however you want to order it)

So #1 is already eliminated therefore it's 1/2. If the order was important 2/3 would be correct. The question is not asking "What are the odds the younger child is a boy?" which it would have to for your answer to be correct.

You don't understand probability theory. Write a simulator for this problem, and you'll see that the answer to p(xy=BG or xy=GB | x=G or y=g) = 2/3. But that is taking order into account.

In your way of reasoning, i.e. saying that GB is the same as BG, the weight of GB or the prior probability if you want, has to be taken into account. For GB/BG it is 1/2, whereas for GG it is 1/4. So now you have to divide 1/2 by (1/2 + 1/4) which still gives 2/3.

• (cs)

Some entertaining comments today! :-D

I particularly enjoyed the Java implementation (implementing different strategies as different objects tickled me).

Also, thanks to the person who noted that this is a Random Walk. I hadn't heard that term before.

I implemented the simulation in PHP (before reading any of the comments). It seems readable and simple to me: http://pastebin.com/m2c191ce8

Anyways, good times.

• (cs)

I wrote this as a Console Application in C# using Visual Studio 2005.

using System;
using System.Collections.Generic;
using System.Text;

namespace ThePerch
{
class Program
{

static void Main(string[] args)
{
Console.WriteLine("Result: " + PerchStrategy(10, 8, 400));
}

public static int PerchStrategy(int startingBankroll, int numTables, int desiredBankroll)
{
int bankroll = startingBankroll;
int betColor = 0;	//0 = black, 1 = red
int totalBets = 0;
int spins = 0;
RouletteTable[] tables = new RouletteTable[numTables];
for (int i = 0; i < numTables; i++)
tables[i] = new RouletteTable();
RouletteTable myTable = null;

while (bankroll >= 10 && bankroll < desiredBankroll)
{
myTable = null;
Console.WriteLine("On the Perch. Bankroll = " + bankroll);
//Reset the tables.  (We can't watch them while we're playing a table.)
foreach (RouletteTable t in tables)
{
t.Black = 0;
t.Red = 0;
}

Console.WriteLine("Finding a table...");
spins = 0;
while(myTable == null)
{
foreach (RouletteTable t in tables)
{
t.Spin();
spins++;
if (t.Red >= 4)
{
myTable = t;
betColor = 0; //black
Console.WriteLine("Picked a table after witnessing " + spins + " spins.  Betting black...");
break;
}
else if (t.Black >= 4)
{
myTable = t;
betColor = 1; //red
Console.WriteLine("Picked a table after witnessing " + spins + " spins.  Betting red...");
break;
}
}
}
//We've picked a table now.

bankroll = bankroll - 10; //Bet 10.
totalBets++;
if (myTable.Spin() == betColor)
{
//Won.
bankroll = bankroll + 20;
Console.WriteLine("Won on first spin.  Bankroll = " + bankroll);
}
else
{
//Lost.
Console.WriteLine("Lost on first spin.  Bankroll = " + bankroll);
if (bankroll < 15)
continue;	//Can't bet a second time.

bankroll = bankroll - 15; //Bet 15.
totalBets++;
if (myTable.Spin() == betColor)
{
bankroll = bankroll + 30;
Console.WriteLine("Won on second spin.  Bankroll = " + bankroll);
}
else
{
Console.WriteLine("Lost on second spin.  Bankroll = " + bankroll);
}
}
Console.WriteLine("Returning to the Perch...");
Console.WriteLine();
}
Console.WriteLine("Total Bets = " + totalBets);
return bankroll;
}
}

public class RouletteTable
{
private int red = 0;
private int black = 0;
public int Red
{
get { return red; }
set { red = value; }
}
public int Black
{
get { return black; }
set { black = value; }
}
private int[] arrBlack = {2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35};
private int[] arrRed = {1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36};
private int[] arrGreen = {37, 38};
private Random r = new Random();
public int Spin()
{
int value = r.Next(38);

if (Array.IndexOf(arrGreen, value) >= 0) //green
{
red = 0;
black = 0;
return -1;
}
else if (Array.IndexOf(arrBlack, value) >= 0) //black
{
red = 0;
black++;
return 0;
}
else //if (Array.IndexOf(arrRed, value) >= 0) //red
{
black = 0;
red++;
return 1;
}
}
}
}

• facepalm (unregistered)

So is the programmer supposed to just ignore the numerous statistical fallacies?

are you supposed to code it such that any time 4 blacks come up, a red is guaranteed to be next?

I think instead I'll just write a script that outputs your longterm expected bankroll:

echo "0";

There, done!

• Anonymous Coward (unregistered)

People are saying that roulette can't be beaten, that the House always wins. This is not true. There is at least one way to beat the House that doesn't involving rigging the wheel or punching the croupier when you lose or the like. And that is to abuse physics. In a casino, there is a physical wheel, after all, and you can certainly predict where the ball will land. This only applies if the casino lets people continue to place bets after the wheel is already spinning, of course, since the starting location and how hard the croupier pulls the wheel varies each game.

Some enterprising grad students actually pulled this off; I recommend "The Eudaimonic Pie" for more on this. It's an amusing book. This was back in ~1981, too, before computer miniaturization had really taken off... they had computers stowed in their phones, Maxwell Smart style, and the associate used radio signals to shock the better's hand in a specific spot to tell him where to bet. Pretty neat stuff.

The method was something like this: Divide the wheel into octants. Measure the speed of one revolution of the wheel - as in, click a button when 00 is at the bottom of the wheel, then click again when it has returned. Calculate which octant the wheel will stop at based on its speed (and a bunch of tests with a similar wheel and an estimate of the degree of tilt on the wheel). They never made tons of money off it due to having to research too many wheels, but at their best they were getting the octant right 1/3 of the time on a bet that's supposed to only pay off 1/8 of the time.

• darkscout (unregistered)

So much arguing over it. Of course it doesn't make sense, but drunk logic rarely does.

And no you aren't supposed to code it so that it 4 blacks -> 1 red. code it like it'd happen in real life.

Never once made money... Matlab.Some assumptions: When you go to bet on a table you 'forgot' what tables had how what count. If bet>bankroll, you quit.

For some reason I can't get it to accept my code.. http://pastebin.com/mce5911a

• Justin (unregistered)

Here's a javascript dabbling, it includes a wheel emulator.

I've yet to zero out yet though, so I'm not sure it's working right.

<script type="text/javascript">

var wheel =  {
consecutive: 4,
smoothness: 1000,
wheel: Array('0','32','15','19','4','21','2','25','17','34','6','27','13','36','11','30','8','23','10','00','5','24','16','33','1','20','14','31','9','22','18','29','7','28','12','35','3','26'),
perch : function(bet) { var hits = 0; var last = ''; while(hits<this.consecutive) {="" var="" result="this.spin();" if(result[0]="=last" )="" {="" hits++;}="" else="" {hits="0;}" last="result[0];" }="" var="" result="this.spin();" if(result[0]="=last)" {="" return="" (bet*2);="" }="" else="" {="" return="" (bet*-1);="" }},="" spin:function()="" {var="" spin="0;var" position="0;var" rotations="this.getrotations((this.smoothness/2),this.smoothness);" while(spin<rotations)="" {="" var="" skip="this.bounce();for(var" p="0;p<=skip;p++)" {position++;if(position="">37) position=0;}if(!(parseInt(this.wheel[position]) % 2)) {var color = 'black';} else {var color = 'red';}spin++;}return new Array(color,this.wheel[position]);},
bounce:function() { return Math.floor(Math.random()*11); },
getrotations:function(min,max) {var rotations = 0;while(rotations<min) {="" rotations="Math.floor(Math.random()*max);}return" rotations;}="" };="" function="" perch(bank,tables,end,consecutive)="" {="" if(typeof="" consecutive="=" 'undefined')="" {="" consecutive="4;" }="" while(bank<end="" &&="" bank="">0) {
for(var table=0;table<tables;table++) {="" var="" game="wheel;" game.consecutive="consecutive;" var="" result="game.perch(10);" bank+="result;" document.write('<p="">table ' + table + ' result: ' + result + ', bank: ' + bank + '<p></p>');
if(bank>end || bank<1) break;
}
}
return bank;
}

var result = perch(100,4,1000);

</script>
</tables;table++)></min)></this.consecutive)>
• Anonymous Coward (unregistered) in reply to mb
mb:
A drunk man normally has an even chance to take a 1 foot step to the left or a step to the right (no, he's not doing the Timewarp). Because we are sadists, we place a drunkard 1 foot to the right of a cliff. Also, the ground is slightly tilted, which means this poor besotted fellow is slightly (3%) more likely to take a step to the right. However, if he manages to wander 400 feet uphill, there is a kindly social worker who will take him away to rehab.

What are the chances that our drunk ends up dead at the bottom of a cliff?

The odds are a bit better than this. Assuming a fixed 10 dollar bet, and starting with 10 dollars, the social worker is only 40 steps away. Also, the bet size is not in fact fixed, so we shouldn't force our random walker to only move one step at a time. Continuously betting the max gives a 1/64 chance to win outright, and in fact this would be the optimum strategy if our gambler was trying to win 320 dollars (or 640 dollars). As is, it gets a bit foggy as the gambler should start only betting what he needs to get to 400 at some point, giving him some room to recover on losses. Doesn't change the fact that when the house is against you, you want to make as few bets as possible to reduce the effect of the law of large numbers. It's much easier to get lucky 6/10 times than 60/100 times, for example, so we want to be making large bets.

• Justin (unregistered)

I fixed my js, outcome is as expected, \$0

<script type="text/javascript">

var wheel =  {
consecutive: 4,
smoothness: 1000,
wheel: Array('0','32','15','19','4','21','2','25','17','34','6','27','13','36','11','30','8','23','10','00','5','24','16','33','1','20','14','31','9','22','18','29','7','28','12','35','3','26'),
perch : function(bet) { var hits = 0; var last = ''; while(hits<this.consecutive) {="" var="" result="this.spin();" if(result[0]="=last" )="" {="" hits++;}="" else="" {hits="0;}" last="result[0];" }="" var="" result="this.spin();" if(result[0]="='green')" {="" return="" (bet*-1);="" }="" else="" {="" if(result[0]!="last)" {="" return="" (bet);="" }="" else="" {="" return="" (bet*-1);="" }}},="" spin:function()="" {var="" spin="0;var" position="0;var" rotations="this.getrotations((this.smoothness/2),this.smoothness);" while(spin<rotations)="" {="" var="" skip="this.bounce();for(var" p="0;p<=skip;p++)" {position++;if(position="">37) position=0;} if(this.wheel[position]=='0' || this.wheel[position]=='00'){ color =  'green'; } else { if(!(parseInt(this.wheel[position]) % 2)) {var color = 'black';} else {var color = 'red';} } spin++;}return new Array(color,this.wheel[position]);},
bounce:function() { return Math.floor(Math.random()*11); },
getrotations:function(min,max) {var rotations = 0;while(rotations<min) {="" rotations="Math.floor(Math.random()*max);}return" rotations;}="" };="" function="" perch(bank,tables,end,consecutive)="" {="" if(typeof="" consecutive="=" 'undefined')="" {="" consecutive="4;" }="" while(bank<end="" &&="" bank="">0) {
for(var table=0;table<tables;table++) {="" var="" game="wheel;" game.consecutive="consecutive;" var="" result="game.perch(10);" bank+="result;" document.write('<p="">table ' + table + ' result: ' + result + ', bank: ' + bank + '<p></p>');
if(bank>end || bank<1) break;
}
}
return bank;
}

var result = perch(100,4,1000,5);

</script>
</tables;table++)></min)></this.consecutive)>
• Justin (unregistered) in reply to Justin
Justin:
I fixed my js, outcome is as expected, \$0

It's funny watching it run:

played 39 times, highest cash on hand was 110 played 175 times, highest cash on hand was 200 played 1007 times, highest cash on hand was 420 played 79 times, highest cash on hand was 100

• Buddy (unregistered) in reply to Anonymous Coward
Anonymous Coward:
People are saying that roulette can't be beaten, that the House always wins. This is not true. There is at least one way to beat the House that doesn't involving rigging the wheel or punching the croupier when you lose or the like. And that is to abuse physics. In a casino, there is a physical wheel, after all, and you can certainly predict where the ball will land. This only applies if the casino lets people continue to place bets after the wheel is already spinning, of course, since the starting location and how hard the croupier pulls the wheel varies each game.

Some enterprising grad students actually pulled this off; I recommend "The Eudaimonic Pie" for more on this. ...

It was because of this that roulette wheels now have little pegs and ornamental obstructions so that the ball bounces around randomly before landing.

• Dave (unregistered)

It's unclear how large an initial bet is when you approach a table. Is it always \$10?

• Justin (unregistered)

Are we not allowed to post the obligatory XKCD links anymore? SADFACE.

• Joe (unregistered) in reply to Anonymous Coward

(Win at Roulette by predicting where the ball will land)

Yeah, I remember that Knight Rider episode where Michael held up his watch (camera) and Kitt figured out which number the ball would land on so he'd win a bunch of money.

No, I didn't have anything better to do in the 1980s.

--Joe

• Pat (unregistered) in reply to Yazeran

So YOU'RE the guy the caused the world recession!

It's called the Martingale system. The downside is no matter the size of your bet, you're only winning one betting unit. Consequently the risk of ruin is high (e.g. 10 straight losses mean a \$5120 bet on the board, and \$5110 lost on the previous bets. If you win, you win \$10240, or \$10 net)

• Youse gotta be kiddin me (unregistered)

None of you ever played Grim Fandango? You don't win roulette because of random chance, it's fixed!

• Sal (unregistered) in reply to Sequence, it's all about the probability of the sequence....

It's funny how you're attacking his statement (rightfully so) but incorrectly.

100 black followed by 100 red is infinitely more likely than R-B-R-B repeated forever. 100 B followed by 100 R is just as likely as any other 200 spin sequence; it's your chances of predicting that (or any other 200 spin sequence) are effectively nil.

Those knowledgeable about probability are those who are keeping their money away from a casino.

Also your proposed bet is just stupid without odds. An even money bet on one side picking a 1 : 2^100 event -- you're an idiot. I'd take your bet on the proper odds (you giving me \$1000 if it happens; me giving you \$1000 / 2^100 if it doesn't).

• Travis (unregistered)

import java.util.*;

public class Perch {

private static int starting_money = 10;
private static final int number_of_tables = 3;
private static final int desired_bankroll = 400;

public static void main(String[] args) {

Random r = new Random();
Table[] tables = new Table[number_of_tables];
for(int i=0; i<tables.length; i++)
tables[i] = new Table(r.nextInt());

int games_played = 0;
while(starting_money > 1 && starting_money < desired_bankroll) {
int i = 0;
while(true) {	// find a table to bet on
if(tables[i%tables.length].fourInARow()) break;
tables[(i++)%tables.length].spin();
}
if(tables[i%tables.length].spin()) starting_money /= 2;
else starting_money *= 1.5;
games_played++;
}
System.out.println("Final bankroll: \$" + starting_money + " after " + games_played + " games played");
}

static class Table {
private List<Boolean> history;
private Random rand;

public Table(int seed) {
rand = new Random(seed);
history = new ArrayList<Boolean>();
}

public boolean spin() {
return history.get(history.size()-1);
}

public boolean fourInARow() {
if(history.size() < 4) return false;
int last = history.size()-1;
return history.get(last) && history.get(last-1) && history.get(last-2) && history.get(last-3);
}
}

}

• EngleBart (unregistered) in reply to Alex Papadimoulis

I have tried "The Perch 1.0" twice; both times with play money at casino nights. 1.0 version means choose a color, bet every time, double next bet if you lose, retain half of all earnings if you win. As with all house based gambling, you always have to quit when you are ahead! This is why you should only play poker at casinos. Once you have payed your table fee, the casino does not care if you win someone else's money.

The first time it worked like a champ, I amassed \$20,000 dollars starting with a \$1,000 dollar stake for a \$10 cover charge. Unfortunately, the bar would not accept the quote-unquote funny money as payment for beverages. They were selling Cuba Libres for \$1 so I could live with that.

The second time I used "The Perch 1.0", I bet red, and black showed up 10 times in a row. The roulettier (I am not sure what you call them) said that she had never seen such a thing, but she happily continued to confiscate my funny money even though the last few, large piles of bills were stained with tears. (Or was it sloshed beer?)

P.S. I bet a straw poll of WTF readers will show that very few enjoy the mind numbing effects of slot machines. (Soma)

• H2 (unregistered)

I wrote a brute-force-solution in perl, just for testing randomness. After 1million runs with each starting with 10\$, trying to get 400\$ at 5 tables, I got: »Chance in this case is: 0.203800000000001%« I should mention, that I allowed to play at multiple tables at the same time.

Regards, H2

• (cs)

Tip for the Firefox users: if you hate that the preformatted code is double newlined put this to your userContent.css:

@-moz-document url-prefix(http://thedailywtf.com/) {
pre br {
display: none ! important;
}
}

(if you don't know what userContent.css is than find file with name userContent-example.css on your disk, go to that folder, rename it to userContent.css and put the code from this comment into it. Save and restart firefox.)

Disclaimer: if something goes wrong, I'm really sorry :-)

FAQ: Q: Nothing happened. A: You probably didn't restart firefox succesfully. The most reliable way to do this is to select File\Quit and than run firefox again.

• Domenic (unregistered)

Quick and dirty in PHP (SUPER Q&D, I'm at work so I threw it all together as fast as I could. The code is crap.) pastebin dot com / m3175c427

You can either do N number of runs for some statistics, or see what a single run looks like.

Stats example output:

Played 5000 games with 137028 individual gambles.

Won 30 games

Lost 4970 games

Started with 10 monies, and tried to hit 400 monies.

Probability of hitting the goal of 400 monies with a sample size of 5000: 0.6%

and an example single run:

Beginning. Bankroll is 10, minbet is 10, payoff ratio is 1.

Hit red 4 times! Begin betting event! Lost the spin by betting red on black. Lost the spin. Upping bet to 150%. Bankroll is 0 Lost the spin by betting red on black. Lost the respin. Bankroll is -15. End of the betting event. Returning to perch.

Hit black 4 times! Begin betting event!

You can't place any more bets with your n00b bankroll of -15 Tried to bet 10

SUMMARY Won: 0 Lost: 2 Ending bankroll: -15

-Dom

• (cs)

Here's my first crack at a Praxis on here. In C#. It loops through the tables one at a time, waiting for each one in turn to return four-in-a-row; this should be refactored to be asynchronous, but I didn't feel like going that far with it.

Also, Alex said the only output should be the final result, but this one prints out the bankroll, betting amount and result at every bet.

The betting amount is a random number between 10 and the current bankroll. It isn't restricted to multiples of 10, so it's possible the bankroll can be less than the minimum \$10 bet without hitting zero. Therefore, we jump out of the loop when bankroll is less than \$10.

Here are a sample losing and winning run, based on a starting bankroll of \$100, two tables, and a desired bankroll of \$400:

Bankroll = 100 Betting 19 on red: lose Bankroll = 81 Betting 71 on red: lose Bankroll = 10 Betting 10 on red: win Bankroll = 20 Betting 15 on red: win Bankroll = 35 Betting 11 on red: lose Bankroll = 24 Betting 22 on red: lose Final bankroll = 2

Bankroll = 100 Betting 23 on red: lose Bankroll = 77 Betting 20 on red: lose Bankroll = 57 Betting 49 on black: win Bankroll = 106 Betting 73 on black: win Bankroll = 179 Betting 123 on black: win Bankroll = 302 Betting 171 on black: win Final bankroll = 473

using System; using System.Collections.Generic; using System.Linq;

namespace ConsoleApplication1 { class Program { static void Main(string[] args) { // TODO: code for user input of parameters perch(100, 2, 400); Console.ReadKey(); }

public static void perch(decimal bankroll, int tableCount, decimal targetBankroll)
{
// TODO: verify that initial bankroll >= 10M, tableCount > 0, targetBankroll > bankroll, etc.

Random blowThatMoneySucker = new Random(); // For determining how much to bet

List<RouletteTable> tables = new List<RouletteTable>();
for (int i = 0; i < tableCount; i++)
{
}

// TODO: make this asynchronous rather than a loop-in-a-loop
while ((bankroll >= 10M) && (bankroll < targetBankroll))
{
foreach (RouletteTable rouletteTable in tables)
{
Console.WriteLine("Bankroll = " + bankroll.ToString());
decimal betAmount = blowThatMoneySucker.Next(10, Convert.ToInt32(bankroll + 1));
RouletteTable.slotColor colorToBet = rouletteTable.getFourInARow();
bool winOrLose = rouletteTable.bet(colorToBet);
string output = String.Format("Betting {0} on {1}: {2}", betAmount, colorToBet, (winOrLose) ? "win" : "lose");
Console.WriteLine(output);
bankroll = (winOrLose) ? bankroll + betAmount : bankroll - betAmount;
if ((bankroll < 10M) || (bankroll >= targetBankroll))
{
Console.WriteLine("Final bankroll = " + bankroll.ToString());
break;
}
}
}
}
}

public class RouletteTable
{
private int[] red = { 1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36 };
private int[] black = { 2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35 };
public enum slotColor { black, red, green }
Random spin = new Random();

public slotColor getFourInARow()
{
slotColor lastColor = slotColor.green;
slotColor thisColor = slotColor.green;
int count = 0;

do
{
lastColor = thisColor;
thisColor = getOneSpin();
count = (thisColor == slotColor.green) ? 0 : (thisColor != lastColor) ? 1 : count + 1;
} while (count < 4);
return (thisColor == slotColor.black) ? slotColor.red : slotColor.black;
}

public bool bet(slotColor colorToBet)
{
return (colorToBet == getOneSpin());
}

private slotColor getOneSpin()
{
int thisSpin = spin.Next(0, 38);
return (red.Contains(thisSpin) ? slotColor.red : (black.Contains(thisSpin) ? slotColor.black : slotColor.green));
}
}

}

• Michael Kolczynski (unregistered)

This is a classic probability problem and large numbers does nothing to affect the probability. To say "I bet you the next 5 won't be red" is completely different than "I bet you the next one won't be red since the last 4 were." A roulette wheel has 36/38 red or black numbers, and 18/38 of each. Therefore, the probability of winning on any play is approx 47%

Based on the assumption that we go all in each play, if we lose once we're out (the strategy simply said "place a bet").

Therefore we must win 5.32~ consecutive bets in order to turn 10 into 400 [log2(40)]. So the probability of winning 5.32 consecutive bids is 1.87% (47%^5.32).

If I get a chance I'll post some probabilities of not going all in...

Gee, BYOC with TRWTF: Mentioning my hometown without having "The Windsor Ballet" be one of the major draws. :)

• (cs)

Perl hackers can win this, even if their code states perfectly clearly that they will always lose.

\$ cat > one_billion_dollars
#! /usr/bin/perl
print "\$0\n"; # You will always lose all your money.
• (cs) in reply to Jay
Jay:
As a nervous father I was worried about her getting a job at a casino, but in reality it probably keeps her away from gambling: she sees how the only people making money at this are the casino owners.
True, in my only visit to a casino (Shreveport, LA) I didn't win any money. However, while my girlfriend played the slots, I wandered around looking at the sights (mostly triple addicts (cigarettes, gambling and booze)) and drinking free drinks for a couple of hours. I spent a nickel in a slot now and again just to keep the free stuff coming.
• Tyrathect (unregistered)

I ran the following:

5 tables, wait for 4 reds then bet \$10 on black.

if that hits, go back to perch. If it doesn't bet \$15 on black on the same table. Whether that hits or not, return to perch.

Start with \$100, quit when you get to \$0 or \$400

I ran that a million times. What I got back was that it reached \$400 39964 times out of a million. About 4% of the time.

given that you make \$300 or lose \$100, You've got about a 12% chance of making money by repeatedly playing.

• Jim (unregistered)

Here's the best roulette strategy that I've ever seen:

'm going to give you a secret roulette system that really works. It will cut the house advantage to literally nothing, if you believe in it enough to never get frustrated and switch tactics. What I'm going to say may seem strange, but here goes.

First, never bet simply red or black. Also don't bet odd or even. These are equally poor, consistently losing wagers.

Second, don't be suckered into betting zero or double zero, despite what some experts may suggest. This may seem like you're betting with the house, but for technical reasons you are actually betting against the house -- and you are taking the worst of it.

So, in order to negate the house advantage, you MUST stick to straight non-green number bets. All odd red numbers turn out to be bad choices, based on over two trillion computer trials. Don't bet them.

All even black numbers fair poorly, and cannot be bet, for much the same reason, which I won't explain here.

Let's get straight to the money-saving advice. Any bet you decide to make MUST cover only even-red or odd-black numbers. There are no exceptions.

Finally, you need to be very disciplined in excluding the number 30 and the group of consecutive numbers that begins with 11 and continues clockwise through and including 14.

This system may seem mystical, but I take gambling quite seriously, and this works for me.

Source: http://www.poker1.com/absolutenm/templates/mculib_articles.aspx?articleid=164&zoneid=3

• pb (unregistered)

I did something for this a while back, very similar to what is mentioned here

http://webpaul.net/content/InstaGamble.asp?bettingX=1&winningLimit=5&pocketMoney=1000&entryPoint=0

• Boogaloo (unregistered)

After having implemented this betting strategy (vb.net winforms) I've come to the conclusion that The Perch is an extremely poor betting strategy. In the example story the characters were lucky to have even doubled their money. More often than not one will lose the initial betting round.

• Justin Drury (unregistered)

My very long, object oriented, brute force method. After about 20-30 tries, it has not won yet.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Perch
{
public delegate void PlayerUpdateHandler(string message);

public enum SlotColor
{
GreenZero,
GreenDoubleZero,
Red,
Black
}

public class RouletteTable
{
private List<SlotColor> slots;

public List<SlotColor> Rounds { get; private set; }
public string Name { get; set; }

private RouletteTable() { }

public RouletteTable(string tableName)
{
Name = tableName;
GenerateTable();
}

private void GenerateTable()
{
slots = new List<SlotColor>();
Rounds = new List<SlotColor>();
for(int i = 1; i <= 38; i++)
{
if(i == 1)
{
continue;
}
if(i == 18)
{
continue;
}
if(i % 2 == 0)
{
continue;
}
}
}

public void PlayRound()
{
Random rand = new Random((int)Math.Ceiling((double)(Environment.TickCount * DateTime.Now.Millisecond) * .132));
int number = rand.Next(slots.Count);
var a = slots.ElementAt(rand.Next(slots.Count));
Rounds.Insert(0, a);
}

}

public class Player
{
private int desiredBankRoll;
private int minBet = 1;
private int maxBet = -1;

public int Money { get; private set; }
public List<RouletteTable> WatchedTables { get; private set; }

public event PlayerUpdateHandler PlayerUpdate;

public Player(int bankRoll, int numberOfTables, int desiredBankRoll)
{
Money = bankRoll;
this.desiredBankRoll = desiredBankRoll;
WatchedTables = new List<RouletteTable>();
for(int i = 0; i < numberOfTables; i++)
{
WatchedTables.Add(new RouletteTable(string.Format("Table {0}", i + 1)));
}
}

public Player(int bankRoll, int numberOfTables, int desiredBankRoll, int minBet, int maxBet)
: this(bankRoll, numberOfTables, desiredBankRoll)
{
this.minBet = minBet;
this.maxBet = maxBet;
}

public void Start()
{
OnPlayerUpdate("Starting Perch");
RouletteTable tableToPlay = null;
while(Money > 0 && Money < desiredBankRoll)
{
// Find table with 4 rounds of red or black
OnPlayerUpdate(string.Format("Player has \${0}", Money));
OnPlayerUpdate("Looking for a new table.");
tableToPlay = FindGoodTable();
while(tableToPlay == null)
{
WatchedTables.ForEach(table => table.PlayRound());
tableToPlay = FindGoodTable();
}

if(tableToPlay != null)
{
PlayTable(tableToPlay, GetAmountToBet((int)Math.Floor((double)Money/10), false), false);
tableToPlay = null;
continue;
}
}
OnPlayerUpdate("Player ran out of money.");
}

private void PlayTable(RouletteTable tableToPlay, int amountToBet, bool stopThisRound)
{
if(amountToBet <= 0)
{
return;
}
SlotColor colorToPlay = tableToPlay.Rounds.First() == SlotColor.Red ? SlotColor.Black : SlotColor.Red;
Money -= amountToBet;
OnPlayerUpdate(string.Format("Betting \${0} on {1} at {2}", amountToBet, colorToPlay, tableToPlay.Name));
WatchedTables.ForEach(table => table.PlayRound());
if(tableToPlay.Rounds.First() == colorToPlay)
{
OnPlayerUpdate("Player wins.");
Money += amountToBet*2;
tableToPlay = null;
return;
}
OnPlayerUpdate("Player loses.");
if(!stopThisRound)
{
PlayTable(tableToPlay, GetAmountToBet(amountToBet, true), true);
}
tableToPlay = null;
}

protected virtual void OnPlayerUpdate(string message)
{
if(PlayerUpdate != null)
{
PlayerUpdate(message);
}
}

private RouletteTable FindGoodTable()
{
return WatchedTables.FirstOrDefault(table => (table.Rounds.Take(4).All(x => x == SlotColor.Red) ^ table.Rounds.Take(4).All(x => x == SlotColor.Black)) && table.Rounds.Take(4).Count() == 4);
}

private int GetAmountToBet(int startingBet, bool secondAttempt)
{
int amountToBet = startingBet;
amountToBet = amountToBet < minBet ? minBet : amountToBet;
amountToBet = maxBet > 1 && amountToBet > maxBet ? maxBet : amountToBet;
amountToBet = secondAttempt ? (int)Math.Floor((double)amountToBet*1.5) : amountToBet;
amountToBet = amountToBet > Money ? Money : amountToBet;
return amountToBet;
}

}
}

### Leave a comment on “Knocking Me Off The Perch”

Log In or post as a guest

Replying to comment #: