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")