Created
February 9, 2013 17:09
-
-
Save fredyr/4746097 to your computer and use it in GitHub Desktop.
Project Euler, no. 84, http://projecteuler.net/problem=84
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
board = ["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"] | |
double_board = board * 2 | |
visits = [0] * len(board) | |
cc_cards = ["GO", "JAIL"] + ["NOP"] * 14 | |
ch_cards = ["GO", "JAIL", "C1", "E3", "H2", "R1", "R*", "R*", "U*", "-3"] + ["NOP"] * 6 | |
random.shuffle(cc_cards) | |
random.shuffle(ch_cards) | |
double_rolls = [0, 0, 0] | |
def is_double_roll((x, y)): | |
return x == y | |
def three_double_rolls(): | |
global double_rolls # :S | |
go_jail = sum(double_rolls) == 3 | |
if go_jail: | |
double_rolls = [0, 0, 0] | |
return go_jail | |
def two_dice(): | |
double_rolls.pop(0) | |
dice = (random.randint(1, 6), random.randint(1, 6)) | |
if is_double_roll(dice): | |
double_rolls.append(1) | |
else: | |
double_rolls.append(0) | |
return dice | |
def get_next_card(deck): | |
top = deck.pop(0) | |
deck.append(top) | |
return top | |
def lookup(board_name, current_pos): | |
return board.index(board_name) | |
def step(current_pos, step): | |
return (current_pos + step) % len(board) | |
def linear_search(from_pos, lead): | |
pos = from_pos + 1 | |
while not double_board[pos].startswith(lead): | |
pos += 1 | |
return step(pos, 0) | |
def card_action(current_pos, card): | |
if card in board: | |
return lookup(card, current_pos) | |
else: | |
if card == "NOP": | |
return current_pos | |
if card == "-3": | |
return step(current_pos, -3) | |
return linear_search(current_pos, card[0]) | |
def advance_once(current_pos): | |
if three_double_rolls(): | |
return lookup("JAIL", current_pos) | |
if board[current_pos] == "G2J": | |
return lookup("JAIL", current_pos) | |
if board[current_pos][:2] == "CC": | |
return card_action(current_pos, get_next_card(cc_cards)) | |
if board[current_pos][:2] == "CH": | |
return card_action(current_pos, get_next_card(ch_cards)) | |
return current_pos | |
def advance(current_pos): | |
prev = current_pos | |
next = advance_once(prev) | |
while next != prev: | |
prev = next | |
next = advance_once(prev) | |
return next | |
def move(current_pos): | |
steps = sum(two_dice()) | |
new_pos = step(current_pos, steps) | |
new_pos = advance(new_pos) | |
visits[new_pos] += 1 | |
return new_pos | |
count = 10000 | |
pos = 0 | |
for i in range(count): | |
pos = move(pos) | |
probs = [100 * v / float(count) for v in visits] | |
print probs | |
print "JAIL (6.24%): {val}".format(val=probs[10]) | |
print "E3 (3.18%): {val}".format(val=probs[24]) | |
print "GO (3.09%): {val}".format(val=probs[0]) | |
print "G2J (0.00%): {val}".format(val=probs[30]) | |
result = list(reversed(sorted(zip(probs, range(0, len(probs)))))) | |
print result | |
print "".join(map(lambda (x, y): ("00" + str(y))[-2:], result[:3])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment