Created
January 3, 2021 23:20
-
-
Save napisani/0601abc3fb13cd1e5ca64901a85be463 to your computer and use it in GitHub Desktop.
AoC2020Day23pt2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import List | |
class Link: | |
def __init__(self, cup_num, next_link=None): | |
self.cup_num: int = cup_num | |
self.next_link: Link = next_link | |
self.terminator = False | |
def __repr__(self): | |
return f'{self.cup_num}' | |
class ChainIter: | |
def __init__(self, link: Link): | |
self._link = link | |
self._first = True | |
def __next__(self): | |
if self._first or not self._link.terminator: | |
to_return = self._link | |
self._link = self._link.next_link | |
self._first = False | |
return to_return | |
raise StopIteration | |
class Chain: | |
def __init__(self, cups: List[int]): | |
self._cup_num_to_link = dict() | |
self._cup_link = Link(cups[0]) | |
self._cup_link.terminator = True | |
self._cup_num_to_link[self._cup_link.cup_num] = self._cup_link | |
last_link = self._cup_link | |
for cup_num in cups[1:]: | |
next_link = Link(cup_num) | |
self._cup_num_to_link[next_link.cup_num] = next_link | |
last_link.next_link = next_link | |
last_link = next_link | |
last_link.next_link = self._cup_link | |
def __iter__(self): | |
return ChainIter(self._cup_link) | |
def first(self): | |
return self._cup_link | |
def __getitem__(self, key): | |
return self._cup_num_to_link[key] | |
class Ring: | |
def __init__(self, cups: List[int], pad=False): | |
self._min = min(*cups) | |
self._max = max(*cups) | |
if pad: | |
for x in range(self._max + 1, 1000001): | |
self._max = x | |
cups.append(x) | |
self._game_cnt = 1 | |
self._cups = Chain(cups) | |
self._cur_cup = self._cups.first() | |
def _find_target(self, cups_to_move): | |
def is_good(cup): | |
return cup not in cups_to_move and \ | |
cup != self._cur_cup.cup_num and \ | |
self._max >= cup >= self._min | |
cup_to_find = self._cur_cup.cup_num | |
while not is_good(cup_to_find): | |
cup_to_find -= 1 | |
if cup_to_find < self._min: | |
cup_to_find = self._max | |
return cup_to_find | |
def play_round(self): | |
print(f'-- move {self._game_cnt} --') | |
# print([c for c in self._cups]) | |
cur_cup = self._cur_cup | |
cups_to_move = [] | |
next_link = cur_cup.next_link | |
cups_to_move.append(next_link) | |
for offset in range(0, 2): | |
next_link = next_link.next_link | |
cups_to_move.append(next_link) | |
print(f'cur cup: {self._cur_cup}') | |
print(f'pickup {cups_to_move}') | |
skip_to_link = next_link.next_link | |
cur_cup.next_link = skip_to_link | |
target = self._find_target([cup.cup_num for cup in cups_to_move]) | |
print(f'destination: {target}') | |
target_link = self._cups[target] | |
target_link_next = target_link.next_link | |
target_link.next_link = cups_to_move[0] | |
cups_to_move[-1].next_link = target_link_next | |
self._cur_cup = cur_cup.next_link | |
self._game_cnt += 1 | |
def get_cup_order(self): | |
nums = [] | |
link = self._cups[1] | |
next_link = link.next_link | |
while next_link.cup_num != 1: | |
nums.append(next_link.cup_num) | |
next_link = next_link.next_link | |
return nums | |
def day23(): | |
ring = Ring([int(i) for i in list('394618527')], True) | |
for idx in range(0, 10000000): | |
ring.play_round() | |
final_order = [i for i in ring.get_cup_order()] | |
print(final_order[0]) | |
print(final_order[1]) | |
print(final_order[0] * final_order[1] ) | |
if __name__ == '__main__': | |
day23() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment