project-euler/084_monopoly_odds.py

80 lines
2.2 KiB
Python

#!/usr/bin/env python3
from random import randint, choice
def dice_roll(sides, num):
return sum(randint(1, sides) for i in range(num))
def dice_mask(sides):
mask = [0] * sides*2
for a in range(1, sides+1):
for b in range(1, sides+1):
mask[a+b-1] += 1.0 / sides**2
print(mask)
return mask
def monopoly(n, sides, itrs):
board = [0] * n
board[0] = 1
mask = dice_mask(sides)
for i in range(itrs):
for p in range(n):
for mv in range(len(mask)):
if p+mv+1 < n:
board[p + mv + 1] += board[p] * mask[mv]
else:
board[p + mv - n + 1] += board[p] * mask[mv]
return [sq/sum(board) for sq in board]
def move(board, p, sides, dicenum):
roll = dice_roll(sides, dicenum)
move.rolls.pop(0)
move.rolls.append(roll)
p += roll
if p >= len(board):
p -= len(board)
return p
def simulation(sqnum, sides, dnum, itrs):
cc = (2, 17, 33)
ch = (7, 22, 36)
jail = 10
goto_jail = 30
railways = (5, 15, 25, 35)
utilities = (12, 28)
cards_chance = [0, jail, 11, 24, 39, 5, railways, railways, utilities, -3] + [None]*6
cards_chest = [0, jail] + [None]*14
board = [0] * sqnum
board[0] = 1
p = 0
move.rolls = [0]*3
for i in range(itrs):
p = move(board, p, sides, dnum)
if set(move.rolls) == {2} or p == goto_jail:
p = jail
elif p in cc + ch:
card = choice(cards_chest if p in cc else cards_chance)
if card is None:
pass
elif type(card) is tuple:
if p > max(card):
p = min(card)
else:
p = [sq for sq in card if sq >= p][0]
elif card < 0:
p += card
if p in cc:
card = choice(cards_chest)
if card is not None:
p = card
else:
p = card
board[p] += 1
return [float(sq)/sum(board) for sq in board]
sides = 4
board = simulation(40, sides, 2, 1000000)
squares = [board.index(sq) for sq in sorted(board, reverse = True)]
print(''.join(map(str, squares[:3])))