aoc-2020/d23/main2.py

158 lines
3.6 KiB
Python
Executable File

#! /usr/bin/env python3
from typing import List
from typing import Iterable
from typing import Dict
from typing import Tuple
def listify(cups: Dict[int, int]) -> Iterable[int]:
yield 1
next_cup = cups[1]
while next_cup != 1:
yield next_cup
next_cup = cups[next_cup]
def cups_str(cups: Dict[int, int], current: int) -> str:
return " ".join(
("(" if c == current else "") + str(c) + (")" if c == current else "")
for c in listify(cups)
)
def get_result(cups: Dict[int, int]) -> str:
# Rotate 1 to the front
cup1 = cups[1]
cup2 = cups[cup1]
print(f"cup1: {cup1} cup2: {cup2}")
return str(cup1 * cup2)
def str_to_cups(opening: str, max_cups: int = 0) -> Dict[int, int]:
cups_list = [int(c) for c in opening]
max_cup = max(cups_list)
if max_cups:
cup_limit = max_cups
cups_list += [c for c in range(max_cup+1, cup_limit+1)]
cups = dict(zip(cups_list, cups_list[1:]+cups_list[0:1]))
return cups
def play_round(
cups: Dict[int, int],
current: int,
max_cup: int,
debug: bool = False,
) -> Tuple[Dict[int, int], int]:
if debug:
print(f"cups: {cups_str(cups, current)}")
# Pick up cups
first_cup = cups[current]
second_cup = cups[first_cup]
third_cup = cups[second_cup]
following_cup = cups[third_cup]
# Seal
cups[current] = following_cup
if debug:
print(f"pick up: {first_cup}, {second_cup}, {third_cup}")
# Find destination
dest = current - 1
if dest < 1:
dest = max_cup
while dest in (first_cup, second_cup, third_cup):
dest -= 1
if dest < 1:
dest = max_cup
if debug:
print(f"destination: {dest}")
# Add cups back
following_cup = cups[dest]
cups[dest] = first_cup
cups[third_cup] = following_cup
# Get the new current to the right of old
current = cups[current]
return cups, current
def play_game(
cups: Dict[int, int],
start: int,
max_cup: int,
rounds: int,
debug: bool = False,
) -> Dict[int, int]:
current = start
if debug:
print(f"game: {cups_str(cups, current)} {rounds} rounds")
ten_percent = int(rounds / 10)
for move in range(rounds):
if move % ten_percent == 0:
print(f"{move/ten_percent*10}%")
if debug:
print(f"-- move {move+1} --")
cups, current = play_round(cups, current, max_cup, debug)
if debug:
print("")
if debug:
print("-- final --")
print(f"cups: {cups_str(cups, current)}")
# print(f"result {get_result(cups)}")
return cups
def sample():
# cups = str_to_cups("389125467")
# cups = play_game(cups, 10, debug=False)
# print(f"result {get_result(cups)}")
# cups = str_to_cups("389125467")
# start = 3
# max_cups = 9
# cups = play_game(cups, start, max_cups, 100, debug=True)
# print(f"result {get_result(cups)}")
start = 3
rounds = 10000000
max_cups = 1000000
cups = str_to_cups("389125467", max_cups=max_cups)
cups = play_game(cups, start, max_cups, rounds, debug=False)
print(f"result {get_result(cups)}")
def part1():
cups = str_to_cups("853192647")
cups = play_game(cups, 100, debug=False)
print(f"result {get_result(cups)}")
def part2():
start = 8
rounds = 10000000
max_cups = 1000000
cups = str_to_cups("853192647", max_cups=max_cups)
cups = play_game(cups, start, max_cups, rounds, debug=False)
print(f"result {get_result(cups)}")
if __name__ == "__main__":
# sample()
# part1()
part2()