euler/python/e084.py

144 lines
3.3 KiB
Python

from random import randint
from dataclasses import dataclass
@dataclass
class State:
current_field: int
consecutive_doubles: int
current_cc: int
current_ch: int
NUMBER_OF_FIELDS = 40
DICE_SIDES = 4
NUMBER_OF_ROLLS = 10**5
NUMBER_OF_CARDS = 16
GO = 0
CC1 = 2
T1 = 4
R1 = 5
CH1 = 7
JAIL = 10
C1 = 11
U1 = 12
R2 = 15
CC2 = 17
D3 = 19
CH2 = 22
E3 = 24
R3 = 25
U2 = 28
G2J = 30
CC3 = 33
R4 = 35
CH3 = 36
H2 = 39
# special identifier for chance cards
NR = 100
NU = 101
B3 = 102
CC_CARDS = [GO, JAIL] + [None for i in range(NUMBER_OF_CARDS - 2)]
CH_CARDS = [GO, JAIL, C1, E3, H2, R1, NR, NR, NU, B3] \
+ [None for i in range(NUMBER_OF_CARDS - 10)]
def roll_two_dices():
return (randint(1, DICE_SIDES), randint(1, DICE_SIDES))
def next_state_cc(cc_field, state):
next_field = CC_CARDS[state.current_cc]
state.current_cc = (state.current_cc + 1) % NUMBER_OF_CARDS
if next_field is None:
state.current_field = cc_field
else:
state.current_field = next_field
return state
def next_state_ch(ch_field, state):
next_field = CH_CARDS[state.current_ch]
state.current_ch = (state.current_ch + 1) % NUMBER_OF_CARDS
if next_field is None:
state.current_field = ch_field
elif next_field == NR:
if ch_field == CH1:
state.current_field = R2
elif ch_field == CH2:
state.current_field = R3
elif ch_field == CH3:
state.current_field = R1
elif next_field == NU:
if ch_field == CH1:
state.current_field = U1
elif ch_field == CH2:
state.current_field = U2
elif ch_field == CH3:
state.current_field = U1
elif next_field == B3:
if ch_field == CH1:
state.current_field = T1
elif ch_field == CH2:
state.current_field = D3
elif ch_field == CH3:
state.current_field = CC3
return next_state_cc(state.current_field, state)
else:
state.current_field = next_field
return state
def next_state(state):
next_field = None
d1, d2 = roll_two_dices()
if d1 == d2:
state.consecutive_doubles += 1
else:
state.consecutive_doubles = 0
if state.consecutive_doubles == 3:
state.consecutive_doubles = 0
state.current_field = JAIL
return state
next_field = (state.current_field + d1 + d2) % NUMBER_OF_FIELDS
if next_field == G2J:
next_field = JAIL
elif next_field in [CC1, CC2, CC3]:
return next_state_cc(next_field, state)
elif next_field in [CH1, CH2, CH3]:
return next_state_ch(next_field, state)
state.current_field = next_field
return state
def euler_085():
state = State(GO, 0, 0, 0)
accesses_per_field = [0 for _ in range(NUMBER_OF_FIELDS)]
for _ in range(NUMBER_OF_ROLLS):
state = next_state(state)
accesses_per_field[state.current_field] += 1
p_field = [(float(a) / NUMBER_OF_ROLLS * 100, i)
for i, a in enumerate(accesses_per_field)]
p_field.sort(reverse=True)
solution = ""
for p, i in p_field[:3]:
solution += "{:2d}".format(i)
return solution
if __name__ == "__main__":
solution = euler_085()
print("e085.py: " + str(solution))
assert(solution == "101524")