• chris (unregistered)
    import random
    
    class RouletteTable:
        def __init__(self):
            self.lastRolls = []
    
        def roll(self):
            roll = random.randint(1, 19)
            self._record_roll(roll)
    
        def _record_roll(self, roll):
            color = self._get_color(roll)
            if len(self.lastRolls) == 4:
                self.lastRolls.pop()
            self.lastRolls.insert(0, color)
    
        def _get_color(self, roll):
            if roll >= 2 and roll <= 10:
                return 'R'
            elif roll >= 11 and roll <= 19:
                return 'B'
            else:
                return 'G'
    
        def should_bet(self):
            if not len(self.lastRolls) == 4:
                return False
    
            if self.lastRolls.count('R') == 4 or self.lastRolls.count('B') == 4:
                return True
    
            return False
    
        def last_roll(self):
            if not len(self.lastRolls) >= 1:
                return None
    
            return self.lastRolls[0]
    
    numTables = raw_input("Number of tables? ")
    startMoney = raw_input("Starting bankroll? ")
    desiredMoney = raw_input("Desired ending bankroll? ")
    
    numTables = int(numTables)
    startMoney = float(startMoney)
    desiredMoney = float(desiredMoney)
    
    curMoney = 0
    runs = 0
    while curMoney < desiredMoney:
        tables = [ RouletteTable() for n in range(numTables) ]
    
        curMoney = startMoney
        betAmt = 10
    
        while curMoney > 0 and curMoney < desiredMoney:
            for table in tables:
                table.roll()
                if table.should_bet():
                    last = table.last_roll()
                    if last is 'R':
                        next = 'B'
                    else:
                        next = 'R'
    
                    curBet = betAmt
                    if curMoney < betAmt:
                        curBet = curMoney
    
                    curMoney = curMoney - curBet
    
                    table.roll()
                    if table.last_roll() is next:
                        curMoney = curMoney + 2.0 * curBet
                    else:
                        if curMoney >= curBet * 1.5:
                            table.roll()
                            curMoney = curMoney - curBet * 1.5
                            if table.last_roll() is next:
                                curMoney = curMoney + 2.0 * (curBet * 1.5)
    
        end = curMoney
        print "Ended run with", curMoney
        runs += 1
    
    print "Took", runs, "tries to end up with", desiredMoney
    
  • Anonymous Coward (unregistered) in reply to Jay
    Jay:
    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 writer seems to be trying to make an ethical point with this analogy.

    I doubt it. Drunks are pretty much the canonical example in random walk scenarios, nothing to do with moralizing. Drunks near the cliff are one-dimensional, drunks in the desert trying to make it back to the oasis are two-dimensional, the drunk astronaut trying to get back to the space station is the three-dimensional example, and... uh, I guess the drunken astronaut time traveler attempting to make it back to the space station at a specific point in time would be the four dimensional case?

    Bonus question: Given an infinite amount of time, what's the percent chance of a one-dimensional walker returning to the origin (no cliff)? Of a two-dimensional random walker returning to the oasis? Of the three-dimensional drunk astronaut making it back to the space station? The answers might surprise you.

  • JL (unregistered)

    Another Python implementation:

    import random
    
    class Table(object):
        def __init__(self):
            self.history = []
            self.slots = ['0', '00'] + ['red'] * 18 + ['black'] * 18
    
        def spin(self):
            self.history.append(random.choice(self.slots))
            self.history = self.history[-4:]
    
        def bet(self, color, amount):
            if self.history[-1] == color:
                return amount
            else:
                return -amount
    
        def four_in_a_row(self):
            if self.history[-4:] == ['red'] * 4: return 'red'
            if self.history[-4:] == ['black'] * 4: return 'black'
            return None
    
    class OutOfCashException(Exception):
        pass
    
    def opposite_color(color):
        return {'red': 'black', 'black': 'red'}[color]
    
    def perch(cash, num_tables, end):
        tables = [Table() for i in range(num_tables)]
        num_spins_ref = [0]
        cash_ref = [cash]
    
        def spin_tables(num_spins_ref=num_spins_ref):
            for table in tables:
                table.spin()
            num_spins_ref[0] += 1
    
        def bet(table, color, amount, cash_ref=cash_ref):
            if cash_ref[0] < amount:
                raise OutOfCashException()
            winnings = table.bet(color, amount)
            cash_ref[0] += winnings
            return winnings
    
        try:
            while 0 < cash_ref[0] < end:
                valid_tables = [t for t in tables if t.four_in_a_row()]
                if not valid_tables:
                    spin_tables()
                else:
                    chosen_table = random.choice(valid_tables)
                    color = opposite_color(chosen_table.four_in_a_row())
                    spin_tables()
                    winnings = bet(chosen_table, color, 10)
                    if winnings < 0:
                        spin_tables()
                        bet(chosen_table, color, 15)
        except OutOfCashException:
            pass
    
        return (cash_ref[0], num_spins_ref[0])
    
    def run_trials(num_trials, cash, num_tables, end):
        total_cash_left = 0
        total_spins = 0
        for i in range(num_trials):
            (cash_left, num_spins) = perch(cash, num_tables, end)
            total_cash_left += cash_left
            total_spins += num_spins
        print 'expected amount of cash left:', float(total_cash_left) / num_trials
        print 'expected time wasted (in spins):', float(total_spins) / num_trials
    
    run_trials(num_trials=1000, cash=200, num_tables=10, end=400)
    
  • Andrew Pennebaker (unregistered)

    Cool story. One problem: as statistics tells us, just because previous events were anomalous does not indicate that the following event will be anomalous or normal. In other words, if you manage to flip a coin heads up ten times in a row, that does not mean the next flip should be heads or tails. The probability is still fifty-fifty.

    The chance that a roulette table will get four reds in a row is small, but the chance of a roulette table getting four reds then a black or four reds then another red is the same:

    0.5^4 * 0.5 = 0.5^5

    You don't have to write a lick of code to see that.

  • chris (unregistered) in reply to Andrew Pennebaker

    Yes, everyone knows.

  • Blasd (unregistered) in reply to tedr2
    tedr2:
    I had an argument with my probability professor on the same line. I do not think a knowledge of past events helps in determining future events if the said event are truly unbiased. These events do not know/record their history, so for each future event has a clean (probability ) slate. Somehow i would like to know in technical terms (proof) this idea or theory.

    Don't know about theoryu or proof, but logic dictates....

    Each spin is independent.

    1)The likelihood of any spin being red is 9/19

    2)The likelihood of 5 in a row being red (before any spins) is 9/19 ^5

    2 confuses people, because they think it still applies if 4 spins have already been made, but they are so very, very wrong. The likelihood of the fifth spin being red is 9/19, irrespective of the previous 4 spins. Since the previous 4 spins are in the past, they are a certainty to happen (because they did) so the probability of them turning out as they did (in this case four reds) is 1.

    If I remember simple arithmetic: 1 x 9/19 == 9/19

    What's to prove? It can't be any other way. The likelihood of the past happening the way it did is 1 (or 100% if you like). There is no uncertainty (OOPs - let's not start on Schrodinger and Heisenberg et al - that's not what I mean). To think that the probability of something that happened happening is anything other than 100% we have to

    1. believe Time Travel is possible (and not in a parallel universe set up)
    2. believe that we can never know or learn anything from history (because it could change)
    3. believe in Fairy tales and things (sorry John Titor)
    4. I think I'm getting carried away, suffice it to say, think about it for 15 seconds and you'll see that your instincts that the past does not affect are absolutely correct.

    Of course, where events are not independent there is another kettle of fish...

  • The Drunk (unregistered) in reply to Jay
    Jay:
    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 writer seems to be trying to make an ethical point with this analogy. In fairness to the gambling world, I should point out that the ethics of this example are totally different from the ethics of gambling.

    The most common type of gambling in America today is the lottery. In a lottery, the house does not have the paltry 3% take that a casino does with roulette, but typically more like 50%. BUT ... the money goes to the government. And of course taking money from citizens and giving it to the government is always good, because the government spends money so much more effectively than private citizens do. I've often thought to myself, If only I had a dollar for every time I've heard a small business owner say, "I just wish I could figure out how to run my business as efficiently as the government is run."

    So gambling is fundamentally good.

    Of course if there was a way for the government to collect money from the drunk when he hits the ground at the bottom of the cliff, especially if the money was earmarked for some worthy social goal like education or health care, I'm sure there'd be plenty of people explaining why pushing drunks off cliffs was a fundamentally good thing, too.

    The Government already has his money. They claimed a percentage of it when he bought his Grog. That's the other revenue stream for the government.

    Indecently, I hope the rest of your post was a touch on the sarcastic side. I have had a dollar for every time I've heard "I just wish I could figure out how to run my business as efficiently as the government is run." Currently I have 0.12 (I heard the "I just wish" bit)

  • Murdoch (unregistered) in reply to Blasd
    Blasd:
    tedr2:
    I had an argument with my probability professor on the same line. I do not think a knowledge of past events helps in determining future events if the said event are truly unbiased. These events do not know/record their history, so for each future event has a clean (probability ) slate. Somehow i would like to know in technical terms (proof) this idea or theory.

    Don't know about theoryu or proof, but logic dictates....

    Each spin is independent.

    1)The likelihood of any spin being red is 9/19

    2)The likelihood of 5 in a row being red (before any spins) is 9/19 ^5

    2 confuses people, because they think it still applies if 4 spins have already been made, but they are so very, very wrong. The likelihood of the fifth spin being red is 9/19, irrespective of the previous 4 spins. Since the previous 4 spins are in the past, they are a certainty to happen (because they did) so the probability of them turning out as they did (in this case four reds) is 1.

    If I remember simple arithmetic: 1 x 9/19 == 9/19

    Of course, where events are not independent there is another kettle of fish...

    Yup, just statistics and probability.

    I think what mixes people up is they intuitively understand that getting red 5 times in a row is statistically rare, but they can never reconcile that on the 5th spin, the likelihood of being black isn't any higher than any other spin.

  • (cs) in reply to Alex Papadimoulis
    Alex Papadimoulis:
    As it turned out, Automating the Knight's Tour was a bit more difficult than I had realized. When initially researching the problem, I saw a relatively simple algorithm and figured, oh yeah, I can do that! Of course, without knowing the trick... there was no way I could have solved it in a long coffee break or lunch break. Either way, I was most impressed by DaveC's Excel VBA solution.

    And just to note, The Perch is much, much easier than the Knight's tour. For an added challenge, you can pick a new language.

    Alex - Does this mean I get a DailyWTF sticker? And you spelled my name wrong...
  • Mr.'; Drop Database -- (unregistered)

    I'd just like to say that I appreciate the inclusion of a bonus challenge. Having separate beginner and advanced puzzles should keep everyone amused.

    I haven't had time for this one yet, though, since I was a bit busy on a late but awesome solution to the knight's tour.

  • Mr.'; Drop Database -- (unregistered)

    I wrote some Python 3 code to figure out the probability of going from $10 to $400, which turns out to be 0.25% if my code is correct.

    My algorithm is to make a big array where each element represents the probability of the player winning from that amount of money. I start with arbtitrary estimates and then iteratively refine the array until it stabilises.

    To simplify things a bit, I removed the irrelevant tables and divided all dollar amounts by 5.

    def calcprobability(start, target, verbose=False):
    assert 0 < start < target
    winprob = [i / target for i in range(target+1)]
    winprob[1] = 0
    maxvariation = (0.0000001 ** 2) * target
    while True:
    variation = 0
    for i in range(2, target):
    if i >= 5:
    value = (winprob[i - 5] * 100 +
    winprob[min(i + 2, target)] * 171 +
    winprob[i + 1] * 90) / 361
    else:
    value = (winprob[i + 2] * 9 +
    winprob[i - 2] * 10) / 19
    variation += (winprob[i] - value) ** 2
    winprob[i] = value
    if variation < maxvariation:
    if verbose:
    return winprob
    else:
    print('%.2f%%' % (winprob[start] * 100))
    return

    calcprobability(2,80) -> 0.25%

  • (cs)

    A bit late perhaps, but with my version, everyone can play!

    http://www.itsacon.net/thedailywtf/perch.php

    Source: http://www.itsacon.net/thedailywtf/perch_s.php (not very impressive, wrote it during a 1-hour trainride...)

  • TT (unregistered)

    I tried a similar strategy once.

    Me and my friend walked in with 100 Deutsche Mark (DM) each. We would look for tables with at least 5 blacks or reds in a row, then started betting the minimum (5 DM), doubling when we lost, until we won.

    After 2 hours we walked out with a bit more than 200 DM each.

    I left it at that, but my friend went back two weeks later and lost all on a row of 10 blacks, which - after he was broke - even exended to a series of 15 blacks.

    Regarding the programming challenge: The mean value of your outcome when playing an infinite number of times is zero. In the long run the bank always wins.

  • Mr.'; Drop Database -- (unregistered) in reply to TT
    TT:
    Regarding the programming challenge: The mean value of your outcome when playing an infinite number of times is zero.
    Maybe you should read the question again.
  • There is so much WTF in this I don't know where to start (unregistered) in reply to Itsacon

    I can't comment on the quality of the code, but the output looks great, is simple to use and clearly represents what is going on at each stage.

    WIN!

  • There is so much WTF in this I don't know where to start (unregistered) in reply to Itsacon
    Itsacon:
    A bit late perhaps, but with my version, everyone can play!

    http://www.itsacon.net/thedailywtf/perch.php

    Source: http://www.itsacon.net/thedailywtf/perch_s.php (not very impressive, wrote it during a 1-hour trainride...)

    I can't comment on the quality of the code, but the output looks great, is simple to use and clearly represents what is going on at each stage.

    WIN!

  • Buddy (unregistered)

    My attempt to simulate RL as closely as possible:

    • Player can play only one table at a time.
    • When the player gets off his perch to play a table, the other tables are still running.
    • Player stops when his balance is too low or he meets his goal.

    To do this, I used threads to simulate a player and the roulette tables. Code and sample runs follow:

    #include <stdlib.h>
    #include <pthread.h>
    #include <time.h>
    #include <string.h>
    #include <stdio.h>
    
    #define HISTORY     4
    #define ROUND       15
    #define MINIMUM     10.0
    #define SLEEP(x)    usleep(1000 * (x))
    
    #ifndef bool
    #define bool        unsigned char
    #define false       0
    #define true        (!false)
    #endif
    
    typedef struct
    {
        bool play, pending;
        char history[HISTORY + 1];
        pthread_t thread;
    } ROULETTE;
    
    typedef struct
    {
        double balance, minimum, limit, bet;
        int tables, count;
        ROULETTE *roulette;
        pthread_t thread;
    } PLAYER;
    
    void *SimulateRoulette(void *arg);
    void *SimulatePlayer(void *arg);
    bool PlayStrategy(PLAYER *p, int i, const char *check, const char *win);
    
    int main(int argc, char **argv)
    {
        double balance = atof(argv[1]);
        int tables = atoi(argv[2]);
        double limit = atoi(argv[3]);
    
        ROULETTE *roulette = calloc(tables, sizeof(roulette));
    
        PLAYER player;
        int i, result;
        void *dummy;
    
        srand(time(NULL));
    
        /* Set up the roulette tables and start the simulators */
        for (i = 0; i < tables; i++)
        {
            roulette[i].play = true;
            roulette[i].pending = true;
            pthread_create(&roulette[i].thread, NULL, SimulateRoulette, roulette + i);
        }
    
        /* Set up the player */
        player.count = 0;
        player.minimum = MINIMUM;
        player.tables = tables;
        player.roulette = roulette;
        player.limit = limit;
        player.bet = player.minimum;
    
        do
        {
            /* Reset balance */
            player.balance = balance;
    
            /* Start gambling */
            pthread_create(&player.thread, NULL, SimulatePlayer, &player);
    
            /* Wait until he returns */
            result = pthread_join(player.thread, &dummy);
    
            /* Increment how many times he needed to play */
            player.count++;
    
            /* Output the results */
            printf("round\t%d\tbalance\t$%.0f\n", player.count, player.balance);
    
        } while (player.balance < player.limit);
    
        printf("played %d rounds\n", player.count);
    
        /* Shut down all the tables */
        for (i = 0; i < tables; i++)
            roulette[i].play = false;
    
        /* Wait a bit for all the tables to close */
        SLEEP(ROUND * 2);
    
        return result;
    }
    
    void *SimulatePlayer(void *arg)
    {
        PLAYER *p = arg;
    
        /* Play as long as possible */
        while (p->balance <= p->limit && p->balance >= p->minimum)
        {
            int i;
    
            /* Check all the tables */
            for (i = 0; i < p->tables; i++)
            {
                /* Wheel is ready? */
                if (!p->roulette[i].pending)
                {
                    /* Don't check this roulette wheel until it's ready again */
                    p->roulette[i].pending = true;
    
                    /* Play either all reds or all blacks */
                    if (!PlayStrategy(p, i, "RRRR", "RRRB"))
                        PlayStrategy(p, i, "BBBB", "BBBR");
                }
    
                /* Wait a bit */
                SLEEP(1);
            }
        }
    
        return arg;
    }
    
    void *SimulateRoulette(void *arg)
    {
        ROULETTE *p = arg;
    
        /* Bit of a randomizer so not all tables are changing at once */
        SLEEP(rand() % ROUND);
    
        /* Play until the table is closed */
        while (p->play)
        {
            char color;
            double spin;
            int i;
    
            /* Results are changing */
            p->pending = true;
    
            /* Spin the wheel */
            spin = (double)rand() / (double)RAND_MAX;
    
            /* Set to red, black or green */
            if (spin < 18.0 / 38.0)
                color = 'R';
            else if (spin < 36.0 / 38.0)
                color = 'B';
            else
                color = 'G';
    
            /* Update history */
            for (i = 1; i < HISTORY; i++)
                p->history[i - 1] = p->history[i];
    
            p->history[HISTORY - 1] = color;
    
            /* Results are ready */
            p->pending = false;
    
            SLEEP(ROUND);
        }
    
        return arg;
    }
    
    bool PlayStrategy(PLAYER *p, int i, const char *check, const char *win)
    {
        bool result = !strcmp(p->roulette[i].history, check);
    
        /* Double check - can player play? */
        if (p->balance > p->limit || p->balance < p->minimum)
            return result;
    
        if (result)
        {
            /* Perched */
            /* printf("perched: (%d)\n", i); */
    
            /* Place the bet */
            p->balance -= p->bet;
    
            /* Wait for the wheel to stop */
            while (p->roulette[i].pending)
                SLEEP(1);
    
            /* Flag this roulette wheel */
            p->roulette[i].pending = true;
    
            /* Won? */
            if (!strcmp(p->roulette[i].history, win))
            {
                p->balance += p->bet * 2.0;
                /* printf ("won! r1: (%d) $%.0f $%.0f\n", i, p->balance, p->bet); */
            }
            else
            {
                /* printf ("lost r1: (%d) $%.0f $%.0f\n", i, p->balance, p->bet); */
    
                /* Increase the bet */
                p->bet *= 1.5;
    
                /* Check if there's enough left */
                if (p->bet <= p->balance)
                {
                    /* Place the bet */
                    p->balance -= p->bet;
    
                    /* Wait for the wheel to stop */
                    while (p->roulette[i].pending)
                        SLEEP(1);
    
                    /* Flag this roulette wheel */
                    p->roulette[i].pending = true;
    
                    /* Bet second time and won? */
                    if (!strcmp(p->roulette[i].history, win))
                    {
                        p->balance += p->bet * 2.0;
                        /* printf ("won! r2: (%d) $%.0f $%.0f\n", i, p->balance, p->bet); */
                    }
                    /* else printf ("lost r2: (%d) $%.0f $%.0f\n", i, p->balance, p->bet); */
                }
    
                /* Reset bet */
                p->bet = p->minimum;
            }
        }
    
        return result;
    }
    

    Sample output with $100 initial, four tables, and $400 goal.

    ./roulette 100.0 4 400.0 round 1 balance $0 round 2 balance $0 round 3 balance $5 round 4 balance $5 round 5 balance $5 round 6 balance $405 played 6 rounds

    Sample output with $10 initial, four tables, and $400 goal.

    ./roulette 10.0 4 400.0 round 1 balance $0 round 2 balance $0 round 3 balance $0 round 4 balance $0 round 5 balance $0 ... round 1091 balance $0 round 1092 balance $0 round 1093 balance $0 round 1094 balance $0 round 1095 balance $410 played 1095 rounds

    Using this strategy you have to be very lucky to start out with $10 and end up with $400!

  • Judago (unregistered)

    I didn't read all the comments, a page and half was enough for me, but I did scroll thought to see if their was any hideous windows batch, their wasn't so here one is.

    I tried to condense it a little........

    @ECHO OFF
    SETLOCAL ENABLEDELAYEDEXPANSION
    SET /0=0&SET /37=0
    FOR /L %%A IN (1,2,35) DO SET /%%A=1
    FOR /L %%A IN (2,2,36) DO SET /%%A=2
    :INPUT
    SET /P CASH=PLACE YOU BET AND SEE IF YOU CAN WIN $400 FROM $10 OR $15 ^
    INCREMENTS, MINIMUM STARTING BET $10.
    SET CASH=!CASH:$=!
    SET TEST=!CASH!
    FOR /L %%A IN (0 1 9) DO IF DEFINED TEST SET TEST=!TEST:%%A=!
    IF DEFINED TEST ECHO BAD INPUT!&GOTO INPUT
    IF %CASH% LSS 10 ECHO A LITTLE SHORT BUDDY&GOTO INPUT
    IF %CASH% GEQ 400 ECHO CHEATER!!&GOTO INPUT
    SET BET=10&SET RED=0&SET BLACK=0
    SET BETCOUNT=&SET QUITTIME=0&SET INT=%CASH%
    :PERCH
    IF %CASH% GTR %QUITTIME% SET QUITTIME=%CASH%
    IF %CASH% LSS %BET% GOTO FAIL
    IF %CASH% GEQ 400 GOTO WIN
    SET /A SPIN=%RANDOM% %% 38
    IF %RED% GEQ 4 (
    	CALL :DOBET 1
    	GOTO PERCH
    )
    IF %BLACK% GEQ 4 (
    	CALL :DOBET 2
    	GOTO PERCH
    )
    IF !/%SPIN%!==1 (
    	SET /P =B <NUL
    	SET /A BLACK+=1
    	SET RED=0
    	GOTO PERCH
    )
    IF !/%SPIN%!==2 (
    	SET /P =R <NUL
    	SET /A RED+=1
    	SET BLACK=0
    	GOTO PERCH
    )
    IF !/%SPIN%!==0 (
    	SET /P =Z <NUL
    	SET RED=0
    	SET BLACK=0
    	GOTO PERCH
    )
    
    :DOBET
    SET /A BETCOUNT+=1
    SET /A CASH-=%BET%
    IF !/%SPIN%!==1 SET /P =B <NUL
    IF !/%SPIN%!==2 SET /P =R <NUL
    IF !/%SPIN%!==%1 (
    	SET /A CASH+=BET * 2
    	SET RED=0
    	SET BLACK=0
    	SET BET=10
    	GOTO :EOF
    ) ELSE (
    	IF %BET%==10 (
    		SET BET=15
    		GOTO :EOF
    	) ELSE (
    		SET BET=10
    		SET RED=0
    		SET BLACK=0
    		GOTO :EOF
    	)
    )
    
    :FAIL
    ECHO.&ECHO.&ECHO YOU ENDED UP WITH $%CASH%.
    ECHO THE FINAL BET WOULD HAVE BEEN FOR $%BET%.
    ECHO THE HIGHEST TOTAL WAS $%QUITTIME%.&ECHO.
    ECHO A TOTAL OF %BETCOUNT% BET(S) WERE SUCESSFULLY PLACED.
    PAUSE&ENDLOCAL
    EXIT /B 1
    :WIN
    ECHO.&ECHO.&ECHO YOU MADE $%CASH% FROM THE INITIAL $%INT%.
    ECHO THIS WAS ACHIEVED WITH %BETCOUNT% BET(S).
    PAUSE&ENDLOCAL
    EXIT /B 0
    </pre>
    
  • Buddy (unregistered) in reply to Buddy
    Buddy:
    My attempt to simulate RL as closely as possible:
    • Player can play only one table at a time.
    • When the player gets off his perch to play a table, the other tables are still running.
    • Player stops when his balance is too low or he meets his goal.

    ...

    Currently the code will simulate until the player exceeds the goal. This bug fix ensures player stops when he reaches the goal:

    line 104: just after "/* Play as long as possible */"

        while (p->balance < p->limit && p->balance >= p->minimum)

    line 178: just after "/* Double check - can player play? */"

        if (p->balance >= p->limit || p->balance < p->minimum)
  • Buddy (unregistered) in reply to Buddy
    Buddy:
    My attempt to simulate RL as closely as possible:
    • Player can play only one table at a time.
    • When the player gets off his perch to play a table, the other tables are still running.
    • Player stops when his balance is too low or he meets his goal.

    ...

    For keener bonus points, after five runs, empirically the probability of winning was determined to be 5/16179 or about 1/3200 - not so good.

  • (cs)

    A few years ago, someone pointed out that the Dallas Cowboys had lost every 10th game for many years in a row.

    This is known as "mining past data to look for patterns". If you have a huge set of data (lots of teams and lots of years) to look through, you'll surely find some patterns.

    The odds of 5 routlette blacks in a row starting from zero are different than the odds of one more black after 4 blacks in a row. The odds of the latter are 18 in 38.

    Also, you shouldn't believe that a baseball hitter is "due" for a hit since he had struck out a bunch of times in the past. (Even though there is some ability here, it's partly random too.)

    Finally, on a lighter note: a friend in college flipped a coin 20 times, and got the following sequence:

    HTHTTHHTTTHHHTHHTTHH

    He then calculated the odds of that particular pattern occurring, then concluded that a miracle had just happened, and switched his major to theology. :-)

  • Matti Helin (unregistered)
    Guillaume:
    So here's my function in C:
    int perch(int numTables, int initialMoney)
    {
       return 0;
    }
    Actually this and all the other solutions returning 0 (or 0 - 9 in some cases) are not complete even if the task would be to return the expected end bankroll. This result assumes that the user of the function will use it as expected. An assumption that any programmer knows is false. In this case expected pay will be 0 - 9 only if the player is trying to win (i.e. initial bankroll is smaller than end bankroll).

    Nothing in the specifications says this is necessarily the case. Hence at least one if clause is needed to check if the better is happy with smaller end bankroll than initial. If this is the case expected pay will be initial bankroll (assuming that playing will be stopped after the current cash is equal or larger than desired end bankroll).

    If the programmer decides that this kind of usage of the function is not allowed there should be an error check for bad input or at the very least an assert for this. Hence all solutions just returning zero (or 0 - 9) are in fact wrong or just plain bad programming if you believe end bankroll should always be larger than initial.

    Continuing on kramthegram's rant, I have to point out that the task was to implement a working simulation of Perch strategy, not to point out that expected yield for this strategy as well is zero. Even in a simple case like this there is so much more fun that you can use a good implementation of the function for. For example you could simulate how much longer you can spend playing roulette using Perch strategy with given parameters than when just betting on a single (or random) colour or using Martingale.

    Sal:
    Those knowledgeable about probability are those who are keeping their money away from a casino.
    And yet even the most knowledgeable about probability tend to buy insurances. Aside from statistics, there is another mathematical side to gambling, which is more intuitive when considering rationality of insurances: Game theory. For an individual in expected financial gain/loss is not the best parameter when considering whether or not to take an insurance. Simplified, pain of paying small monthly payments is much more tolerable than huge loss (a potential bankrupcy) if dung hits the fan. Therefore it is completely rational to buy an insurance even though expected payoff is negative.

    Same applies to gambling. Although all the games are in the favour of the house, if the bet is small enough and the jackpot is large enough (as it is in some lotteries), expected utility of playing might come up as positive, even if not considering the entertainment factor of the exitement. What is undeniably stupid, however, is playing with small bets for small wins unless it is done just for fun.

  • Try actually writing the code..... (unregistered) in reply to Andrew Pennebaker

    Yes, except that if you actually wrote the code and ran the simulations you'd see that this actually does work. The trick is it takes lots of games to get the stats to work out.

    Just like Mythbusters, what seems obvious is not always the way it works....

    If you only watch 50 games of roulette it's a tossup, even 500 or 1000 games it's not consistent. But you will notice a trend to winning more than loosing. However at a 1000000 games it's very consistent. You'll end up with about 3% green, 48.5% red and 48.5% black. About 2.6% of these rolls will be four in a row, 1.3% will be five in a row, and 1.2% six in a row.

    This is why the bank always wins at the casino. Sure on the small scale a given player may win or loose, but over time, with 10000s of games the odds smooth out and get consistent. Games at the casino always favor the house over the long term, but using this technique you're actually getting better odds.

    For 1000000 roulette games you'd have approximately 26500 four in a rows, 13000 five in a rows, and 12000 six in a rows. Starting with $100 bankroll and always betting $10 ($15 after a five in a row) you'd have around $195000.

    Of course if your casino had 10 roulette tables running and each table averaged 1 game every 30 seconds, and you Perched for 16 hours a day, it would take you 52 days to go through 1000000 games.

  • (cs)

    Previously I submitted a "balanced" roulette wheel. It remembers its previous spins and then biases later spins to compensate. So each spin of RED makes it a little more likely to spin BLACK next. And it stays close to parity overall.

    Adding a Perch simulator, I find that I can turn $10 into $400 9.16% of the time. Now if I can find a casino to install my special roulette wheels at their tables, I'll head on down and wager my life savings!

    If I replace my wheels with a boring, memoryless wheel then my win percentage goes down around 0.26%. What a depressing universe that would be.

    import random
    
    class Table:
    	def __init__(self):
    		self.wheel = [-1] * 18 + [0] * 2 + [+1] * 18  # a roulette wheel
    		self.history = []  # previous results
    	
    	def spin(self):
    		# Return the color chosen by a spin: -1 (black), +1 (red), or 0 (green)
    		random.shuffle(self.wheel)
    		result = self.wheel.pop()
    		self.wheel.append(-result)  # maintain balance
    		self.history.append(result)
    		return result
    	
    	def streak(self, length):
    		# Return color (if any) of current streak of given length
    		if abs( sum( self.history[-length:] ) ) == length:
    			return self.history[-1]
    
    def perch(bankroll, tables, target):
    	casino = []
    	for i in range(tables):
    		casino.append( Table() )
    	
    	def spinall():
    		print 'Spinning %i wheels:' % tables,
    		for c in casino:
    			print ('green', ' red ', 'black')[c.spin()],
    		print
    	
    	while bankroll >= 10:
    		seat = None
    		while seat == None:
    			spinall()
    			for i in range(len(casino)):
    				if seat == None and casino[i].streak(4):
    					seat = i
    					print 'Moved to hot table #%i' % (i+1)
    		overdue = -casino[seat].streak(4)
    		spinall()
    		if casino[seat].history[-1] == overdue:
    			bankroll += 10
    			print 'Won $10 --> $%i and returned to Perch' % bankroll
    		else:
    			bankroll -= 10
    			print 'Lost $10 --> $%i' % bankroll
    			if bankroll < 15:
    				print 'Failed to cover second bet and returned to Perch'
    				continue
    			spinall()
    			if casino[seat].history[-1] == overdue:
    				bankroll += 15
    				print 'Won $15 --> $%i and returned to Perch' % bankroll
    			else:
    				bankroll -= 15
    				print 'Lost $15 --> $%i and returned to Perch' % bankroll
    		if bankroll >= target:
    			return bankroll
    	return bankroll
    
    if __name__ == '__main__':
    	# Play "The Perch"
    	plays, wins = 0, 0
    	while wins < 100:
    		bankroll = 10
    		print 'Entered the casino with $%i' % bankroll
    		bankroll = perch(bankroll,4,400)
    		print 'Left the casino with $%i' % bankroll
    		print
    		plays += 1
    		if bankroll >= 400:
    			wins += 1
    	print 'Reached $400 target %.2f%% of the time' % ( 100.0 * wins / plays )
    
  • (cs) in reply to thnurg

    Surely it should be quote- phrase being quoted -ENDquote. You can't UNquote something, but you can end the quote.

  • boobie (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:
    Itsacon:
    A bit late perhaps, but with my version, everyone can play!

    http://www.itsacon.net/thedailywtf/perch.php

    Source: http://www.itsacon.net/thedailywtf/perch_s.php (not very impressive, wrote it during a 1-hour trainride...)

    I can't comment on the quality of the code, but the output looks great, is simple to use and clearly represents what is going on at each stage.

    WIN!

    Agreed- I'm hooked!

  • Matti Helin (unregistered) in reply to Try actually writing the code.....
    Try actually writing the code.....:
    For 1000000 roulette games you'd have approximately 26500 four in a rows, 13000 five in a rows, and 12000 six in a rows. Starting with $100 bankroll and always betting $10 ($15 after a five in a row) you'd have around $195000.
    And if you remember that one tenth of the four in a rows and five in a rows end with a green, you'll find out that you still end up losing just as pretty much anyone else playing roulette. You will find out that this happens in simulations as well as in theory if your simulation is set up correctly.
  • Paxinum (unregistered)

    The optimal way of playing is the Kelly Strategy, http://en.wikipedia.org/wiki/Kelly_criterion

    The optimal strategy is to minimize the number of bets, since the expected win is negative. Hence, bet all your money, or the amount needed so that a win makes you reach your goal.

  • Gates and Logic (unregistered)

    only three things to do in Windsor – drink, gamble, and buy Cuban cigars

    I can vouch for the accuracy of this statement. Windsor is pretty boring if you aren't drinking or gambling.

  • pants (unregistered) in reply to Try actually writing the code.....
    Try actually writing the code.....:
    Yes, except that if you actually wrote the code and ran the simulations you'd see that this actually does work.

    I agree 100%. This is why I always keep a 'primed' coin in my pocket. I spend all day flipping this coin until I get eight tails in a row. Once I do that, I put the coin in my pocket because it is primed for heads. Then, when I disagree with my dippy friends, I end up telling them we should flip a coin for it. I always call heads, and because the coin flipped tails the last eight times, the chances of it being heads are 99.8% (that's one minus one half to the power nine).

  • DropDeadFred (unregistered) in reply to boobie

    Cool, but it doesn't work. I always end up broke! ;)

  • Delos (unregistered)

    I disagree that n blacks in a row means that a n+1 black is equally likely as a red. That implies that the difference is 0, while red is actually lim x->inf (n/x) more likely. Clearly this is a critical difference.

  • WORKING STORAGE (unregistered) in reply to Itsacon

    Straight bets should pay off 35 to 1. So just a couple wins and you'd make 400.

  • NotaProgrammer (unregistered) in reply to Alex Papadimoulis

    I ran excel simulations as my weapon of choice. With 50 simulations, (starting at $10, 4 tables and a target of $400), I won merely 22% of the time, with the average number of rolls (on each table) 'til you reach the target: 50 (Maximum 209.

    On the Losing side, the average loss time was merely 20 rolls, with losing everything on the first roll happening a shocking 6 times out of 50. Methinks Excel's Rand() function needs some work . . .

    If you drop the bet amount to 25% of your bankroll, (or table minimums), you raise the winning percentage substantially to 34% (again 50 iterations). This also ups the amount of time 'til you reach the target to ~85 (on average). And if you lose, you will lose early (average: roll 10)

    Switching to 5 in a rows has no real effect, except it takes longer (on average).

    Interestingly, switching to 5, playing a 25% of your money (or minimums) and 1.5x last bet on first loss takes a really long time to win (on average 182 rolls/table (max 717?!)), and posts a win % of 68 (50 trials).

  • NotaProgrammer (unregistered) in reply to NotaProgrammer

    oops, made a mistake in the above, the last trial started with $20.

    Also, follow up: Find optimum strategy by a) win percentage and b) # of rolls (less is better).

  • JCS (unregistered) in reply to Itsacon

    I won only one time (out of dozens). 2 tables, and it took 2,343 rounds!

  • Anonymous (unregistered) in reply to Itsacon

    Pretty decent but it doesn't keep increasing the bet by 1.5x each time. It should go 10 -> 15 -> 22 -> 33 etc.

    if (lose) then if 1.5BET =< WALLET then BET = 1.5BET else BET = WALLET end if

  • Jim (unregistered) in reply to Aris

    There is actually a good reason for that, though it is most likely inapplicable in a real casino.

    Think about if a quarter comes up heads 50 times in a row. A priori, you do not know if the coin is fair or now; thus, the probability that the coin is far is 0.5. After observing the 50 run streak, the posterior probability that the coin is not fair is now much higher. (Similarily, the ABSENCE of long streaks also indicates that the coin is probably not fair. Human generated "random" sequences often have too few long streaks compared to short streaks). This is probably more formally described as the autocorrelation between flips of the coin; high autocorrelation indicates that the next flip is more likely to be heads given that the previous flip was heads, and vice versa.

    Nicolas Nassim Taleb covers this more extensively in The Black Swan. A recommended read.

  • Jon Strayer (unregistered) in reply to Itsacon
    Itsacon:
    A bit late perhaps, but with my version, everyone can play!

    http://www.itsacon.net/thedailywtf/perch.php

    I set it to start with $100 and quite at $150 and got excited when I won six times in a row. :-)

    The final win:loss ratio was 15:10. Which sounds good until you add up the money, then it's 750:1000.

  • Fall (unregistered) in reply to Jon Strayer

    Started with 40 dollars. 663 Rounds later, I was broke.

  • Vman (unregistered) in reply to ThatsALotOfGravy

    So, you're saying the 1 in 2^100 event has a 1 in 2 chance of happening?

  • Vman (unregistered) in reply to ThatsALotOfGravy

    My last comment was in response to this:

    ThatsALotOfGravy:
    [quote user=" 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). However, if it has already been black 99 times in a row, the chance of it being black again is still 1 in 2.
  • AdT (unregistered) in reply to Not always wrong
    Not always wrong:
    If you bet Red or Black and it comes up a Zero, you lose.

    In European Roulette (rules may differ from casino to casino), only inside bets like numbers other than 0 immediately lose on a single zero. Outside bets like colors are "imprisoned" meaning they're still there but cannot be retracted in full.

    Examples:

    1. Place 100 EUR on odd

    2. 0 comes up -> 100 EUR are imprisoned

    3. 7 comes up -> get 100 EUR back (not 200)

    4. Place 100 EUR on odd

    5. 0 comes up -> 100 EUR are imprisoned

    6. 24 comes up -> lose 100 EUR

    7. Place 100 EUR on odd

    8. 0 comes up -> 100 EUR are imprisoned

    9. 0 comes up -> 100 EUR still imprisoned

    10. Switch 100 EUR from odd to red (switching from one outside bet to another is permitted)

    11. 0 comes up -> lose 100 EUR (no triple imprisonment)

    12. Place 100 EUR on black

    13. 0 comes up -> 100 EUR are imprisoned

    14. 0 comes up -> 100 EUR still imprisoned

    15. Retract: You can get back half your imprisoned stake, the other half goes to the house, so get 50 EUR back, lose 50 EUR

    So it's not as bad as immediately losing, but you cannot gain anything from this result either. ISTM that it's always best to retract bets after a second 0 because if anything other than zero comes up next, it makes no difference whether you've retracted half the sum and placed it on an outside bet again, or left it there. However, if a zero comes up, you're better off in the former case (you now have 50 imprisoned EUR instead of nothing at all). That said, it's best not to play Roulette unless you could predict upcoming numbers in some way...

  • AdT (unregistered) in reply to DesGrieux
    DesGrieux:
    So: 4 in a row have a chance of 1:(2^4) - 1, which is 1:15. 5 in a row have a change of 1:(2^5) - 1, which is 1:31. 1:15 are 6,66% 1:31 are 3,22%

    To get the amount which end after a streak of 4: 6,66% - 3,22% = 3,44%

    So the chances to get the other color after you had a streak of 4 should be 3,44:3,22, so just slightly above 1:1.

    It's been a while since i did math in school, so please correct me if necessary ;-)

    You were using the wrong denominator. 1:15 is 1 / (15 + 1) or 6.25%. 1:31 is 3.125%, exactly half the previous probability.

  • shintai (unregistered)

    1 play: profit = (.95(10)-10) 10 plays: profit = 10*(.95(10)-10) N plays: profit = N*(.95(10)-10)

    I find it amazing that people play these games... but being a professional poker player myself I have to appreciate it!

    Blog tracking the long-term progress of my play: www.avoidthe9to5.com

  • Hellrazor (unregistered) in reply to Itsacon

    1687 times and I was broke.

  • rodix (unregistered)

    yeah, some times you may win... playing with initials $1000 I made $2000 most of the times betting $50 ( or $75 sometimes )... but I needed an average of 2000 ball rolls to make it, that is a lot of time

  • Rich F. (unregistered)

    As anyone who has any familiarity with statistics knows, the odds on any number coming up on any given spin are exactly the same.

    If the wheel is "fair" (and if your simulation's random number generator is truly random), then there is absolutely no reason that the fifth spin should come up either red or black - the outcomes of the previous four spins have no influence on the outcome.

    While the red/black bet is the best one that you'll find in the casino, the odds are still with the house (note that there 18 red, 18 black, plus 0 and 00, which are green). So when you bet either red or black, there are 18 possible winning results, and 20 possible losing results.

    So, with a red or black bet, your odds of winning are 20 to 18, or 1.111 to 1 against - on every spin, no matter what the results of the previous n spins were.

  • Rich F. (unregistered) in reply to AdT

    No.

    The odds of red or black (20 to 18 against) are the same on every spin.

    The outcome on previous spins has absolutely no effect on the outcome of the next spin.

    This is a common mistake, but statistically incorrect.

  • taltamir (unregistered) in reply to Itsacon
    Itsacon:
    A bit late perhaps, but with my version, everyone can play!

    http://www.itsacon.net/thedailywtf/perch.php

    Source: http://www.itsacon.net/thedailywtf/perch_s.php (not very impressive, wrote it during a 1-hour trainride...)

    I won the first one I tried... then I lost the next 30... which is as I expected... your odds are still 50%/50% no matter how many times it came up as one result or the other beforehand.

Leave a comment on “Knocking Me Off The Perch”

Log In or post as a guest

Replying to comment #:

« Return to Article