Tag Archives: Simulator

Euler Problem 84


This one was way too fun!

I built a simulator to solve it (as did many) using OOP. Got the answer right away. Lots of ideas posted to the Euler forum, including solutions based on matrix operations.

But c’mon, a simulator is much more fun to build! Plus its so easy to change it to a 4-sided die.

#Euler84

import random
from operator import itemgetter

class Board:
    sqr = [['GO'],['A1'],['CC1'],['A2'],['T1'],['R1'],['B1'],['CH1'],['B2'],['B3'],
    ['JAIL'],['C1'],['U1'],['C2'],['C3'],['R2'],['D1'],['CC2'],['D2'],['D3'],
    ['FP'],['E1'],['CH2'],['E2'],['E3'],['R3'],['F1'],['F2'],['U2'],['F3'],
    ['G2J'],['G1'],['G2'],['CC3'],['G3'],['R4'],['CH3'],['H1'],['T2'],['H2']]
    moves = 0
    def __init__(self):
        for i in self.sqr:
            index = self.sqr.index(i)
            record = i+[0]+[index]
            self.sqr.pop(index)
            self.sqr.insert(index,record)
    def findPos(self, name):
        for i in self.sqr:
            if i[0] == name:
                return self.sqr.index(i)

class Player:
    pos = 0
    def move(self, spaces):
        self.pos += spaces
        if self.pos >= 40:
            self.pos -= 40

class Dice:
    dice1 = [1,2,3,4] # or [1,2,3,4,5,6]
    dice2 = [1,2,3,4] # or [1,2,3,4,5,6]
    dub = [False, False, False]
    def __init__(self):
        random.seed()
    def roll (self):
        random.shuffle(self.dice1)
        random.shuffle(self.dice2)
        self.dub.pop(0)
        if self.dice1[0] == self.dice2[0]:
            self.dub += [True]
        else:
            self.dub += [False]
        return self.dice1[0]+self.dice2[0]

class Chance:
    cards = ['']*6
    cards.extend(['GO','JAIL','C1','E3','H2','R1','RX','RX','UX','-3'])
    def __init__(self):
        random.shuffle(self.cards)
    def pick (self):
        top = self.cards.pop(0)
        self.cards.append(top)
        return top

class Chest:
    cards = ['']*14
    cards.extend(['GO','JAIL'])
    def __init__(self):
        random.shuffle(self.cards)
    def pick (self):
        top = self.cards.pop(0)
        self.cards.append(top)
        return top

if __name__ == '__main__':
    B = Board()
    P = Player()
    D = Dice()
    CH = Chance()
    CC = Chest()
    print "Calculating Moves:",
    while B.moves < 2000001:
        if B.moves % 200000 == 0:
            print B.moves,
        P.move(D.roll())
        spot = B.sqr[P.pos][0]
        if D.dub == [True, True, True]:
            spot = 'JAIL'
        if spot == 'G2J':
            spot = 'JAIL'
        if ['CH1','CH2','CH3'].count(spot) == 1:
            card = CH.pick()
            if ['GO','JAIL','C1','E3','H2','R1'].count(card) == 1:
                spot = card
            elif card == 'RX' and spot == 'CH1':
                spot = 'R2'
            elif card == 'RX' and spot == 'CH2':
                spot = 'R3'
            elif card == 'RX' and spot == 'CH3':
                spot = 'R1'
            elif card == 'UX' and spot == 'CH1':
                spot = 'U1'
            elif card == 'UX' and spot == 'CH2':
                spot = 'U2'
            elif card == 'UX' and spot == 'CH3':
                spot = 'U1'
            elif card == '-3' and spot == 'CH1':
                spot = 'T1'
            elif card == '-3' and spot == 'CH2':
                spot = 'D3'
            elif card == '-3' and spot == 'CH3':
                spot = 'CC3'
        if ['CC1','CC2','CC3'].count(spot) == 1:
            card = CC.pick()
            if ['GO', 'JAIL'].count(card) == 1:
                spot = card
        P.pos = B.findPos(spot)
        B.moves += 1
        B.sqr[P.pos][1] += 1
    B.sqr.sort(key=itemgetter(1), reverse=True)
    print "\nSorted Board Statistics:",
    for n in range (0,40):
        if n % 10 == 0:
            print "\n",
        print "%s:%i:%.2f" % (B.sqr[n][0],B.sqr[n][2],float(B.sqr[n][1])*100/B.moves),
    print "\nAnswer =", B.sqr[0][2], B.sqr[1][2], B.sqr[2][2]