Skip to content

Instantly share code, notes, and snippets.

@mlesniew
Created December 21, 2021 21:15
Show Gist options
  • Save mlesniew/2e6aa5267095b6141cfe24cdb4ef9111 to your computer and use it in GitHub Desktop.
Save mlesniew/2e6aa5267095b6141cfe24cdb4ef9111 to your computer and use it in GitHub Desktop.
import collections
import functools
import itertools
POSITIONS = (9, 6)
DICE = [1, 2, 3]
SUMS = collections.defaultdict(int)
for a, b, c in itertools.product(DICE, DICE, DICE):
SUMS[a + b + c] += 1
def part1(position):
die = itertools.cycle(range(1, 101))
position = list(position)
points = [0, 0]
rolls = 0
turn = 0
while all(p < 1000 for p in points):
a, b, c = next(die), next(die), next(die)
rolls += 3
position[turn] = (position[turn] + a + b + c - 1) % 10 + 1
points[turn] += position[turn]
turn = 1 - turn
return min(points) * rolls
@functools.lru_cache(maxsize=None)
def part2(positions, points=(0, 0), turn=0):
if points[0] >= 21:
return 1, 0
if points[1] >= 21:
return 0, 1
ret = 0, 0
new_positions = list(positions)
new_points = list(points)
for move, count in SUMS.items():
new_positions[turn] = (positions[turn] + move - 1) % 10 + 1
new_points[turn] = points[turn] + new_positions[turn]
wins = part2(tuple(new_positions), tuple(new_points), 1 - turn)
ret = ret[0] + wins[0] * count, ret[1] + wins[1] * count
return ret
print("Part 1: ", part1(POSITIONS))
print("Part 2: ", max(part2(POSITIONS)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment