172 lines
4.1 KiB
Python
Executable File
172 lines
4.1 KiB
Python
Executable File
#! /usr/bin/env python3
|
|
from typing import List
|
|
from typing import Tuple
|
|
|
|
|
|
def cups_str(cups: List[int], current: int) -> str:
|
|
return " ".join(
|
|
("(" if c == current else "") + str(c) + (")" if c == current else "")
|
|
for c in cups
|
|
)
|
|
|
|
|
|
def get_result(cups: List[int], part2: bool = False) -> str:
|
|
# Rotate 1 to the front
|
|
index_1 = cups.index(1)
|
|
|
|
if not part2:
|
|
result = cups[index_1:] + cups[:index_1]
|
|
# Remove 1 from the front
|
|
result = result[1:]
|
|
return "".join((str(c) for c in result))
|
|
else:
|
|
cup1 = cups[index_1+1 % len(cups)]
|
|
cup2 = cups[index_1+2 % len(cups)]
|
|
print(f"cup1: {cup1} cup2: {cup2}")
|
|
return str(cup1 * cup2)
|
|
|
|
|
|
def str_to_cups(opening: str, part2: bool = False) -> List[int]:
|
|
cups = [int(c) for c in opening]
|
|
|
|
if part2:
|
|
max_cup = max(cups)
|
|
cup_limit = 1000000
|
|
cups += [c for c in range(max_cup+1, cup_limit+1)]
|
|
|
|
return cups
|
|
|
|
|
|
def play_round(
|
|
cups: List[int],
|
|
current: int,
|
|
debug: bool = True,
|
|
) -> Tuple[List[int], int]:
|
|
if debug:
|
|
print(f"cups: {cups_str(cups, current)}")
|
|
|
|
cur_i = cups.index(current)
|
|
|
|
# Pick up cups
|
|
picked_up: List[int] = []
|
|
|
|
while len(picked_up) < 3:
|
|
if cur_i+1 < len(cups):
|
|
picked_up.append(cups.pop(cur_i+1))
|
|
else:
|
|
picked_up.append(cups.pop(0))
|
|
cur_i -= 1
|
|
|
|
if debug:
|
|
print(f"pick up: {', '.join((str(c) for c in picked_up))}")
|
|
|
|
# Find destination
|
|
dest = 0
|
|
max_cup = 0
|
|
for c in cups:
|
|
if c < current and c > dest:
|
|
dest = c
|
|
if dest == current-1:
|
|
break
|
|
if c > max_cup:
|
|
max_cup = c
|
|
|
|
if dest <= 0:
|
|
dest = max_cup
|
|
|
|
dest_i = cups.index(dest)
|
|
# Other guy
|
|
# dest = max((c for c in cups if c < current), default=max(cups))
|
|
# dest_i = cups.index(dest)
|
|
# My attempt 1
|
|
# dest = current - 1
|
|
# dest_i = None
|
|
# while dest_i is None:
|
|
# if dest <= 0:
|
|
# # Wrap around to the highest value instead
|
|
# dest = max(cups)
|
|
# try:
|
|
# dest_i = cups.index(dest)
|
|
# except ValueError:
|
|
# # Try the next cup down
|
|
# dest -= 1
|
|
|
|
if debug:
|
|
print(f"destination: {dest}")
|
|
|
|
# Add cups back
|
|
# cups[dest_i+1:dest_i+1] = picked_up
|
|
if dest_i+1 >= len(cups):
|
|
cups += picked_up
|
|
else:
|
|
for cup in reversed(picked_up):
|
|
cups.insert(dest_i+1, cup)
|
|
|
|
# If inserted before the current, move that index up
|
|
if dest_i < cur_i:
|
|
cur_i += 3
|
|
|
|
# Get the new current to the right of old
|
|
cur_i += 1
|
|
cur_i = cur_i % len(cups)
|
|
current = cups[cur_i]
|
|
|
|
return cups, current
|
|
|
|
|
|
def play_game(cups: List[int], rounds: int, debug: bool = True) -> List[int]:
|
|
current = cups[0]
|
|
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, debug=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")
|
|
cups = play_game(cups, 100, debug=False)
|
|
print(f"result {get_result(cups)}")
|
|
|
|
# cups = str_to_cups("389125467", part2=True)
|
|
# cups = play_game(cups, 10000000, debug=False)
|
|
# print(f"result {get_result(cups, part2=True)}")
|
|
|
|
|
|
def part1():
|
|
cups = str_to_cups("853192647")
|
|
cups = play_game(cups, 100, debug=False)
|
|
print(f"result {get_result(cups)}")
|
|
|
|
|
|
def part2():
|
|
cups = str_to_cups("853192647", part2=True)
|
|
cups = play_game(cups, 10000000, debug=False)
|
|
print(f"result {get_result(cups, part2=True)}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# sample()
|
|
# part1()
|
|
part2()
|