Skip to content

Instantly share code, notes, and snippets.

@napisani
Created January 3, 2021 23:20
Show Gist options
  • Save napisani/0601abc3fb13cd1e5ca64901a85be463 to your computer and use it in GitHub Desktop.
Save napisani/0601abc3fb13cd1e5ca64901a85be463 to your computer and use it in GitHub Desktop.
AoC2020Day23pt2
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