from __future__ import annotations from typing import List, Tuple, Optional, Self import weakref from dataclasses import dataclass import re @dataclass class Node: value: str left: str right: str _left_node: Optional[weakref.ReferenceType[Node]] = None _right_node: Optional[weakref.ReferenceType[Node]] = None def move_left(self, node_list: List[Node]) -> Node: if self._left_node is None: node = weakref.ref(list(filter(lambda n: n.value == self.left, node_list))[0]) self._left_node = node return self._left_node() def move_right(self, node_list: List[Node]) -> Node: if self._right_node is None: node = weakref.ref(list(filter(lambda n: n.value == self.right,node_list))[0]) self._right_node = node return self._right_node() def resolve_left_right_nodes(self, node_list: List[Node]) -> Self: idx = 0 while idx < len(node_list) and (self._left_node is None or self._right_node is None): if node_list[idx].value == self.left: self._left_node = weakref.ref(node_list[idx]) if node_list[idx].value == self.right: self._right_node = weakref.ref(node_list[idx]) idx += 1 if self._left_node == None or self._right_node == None: print(f"Invalid Node: {self}") return self def is_A_node(self): return self.value[2] == 'A' def is_Z_node(self): return self.value[2] == 'Z' def __str__(self): return f"{self.value} = ({self.left}, {self.right})" def parse(input_file:str) -> Tuple[str, List[Node]]: the_list = [] with open(input_file) as input: directions = input.readline().replace("\n","") _ = input.readline() while match:= re.match("([A-Z]+) = \(([A-Z]+), ([A-Z]+)\)", input.readline()): node = Node(value=match.group(1), left=match.group(2), right=match.group(3)) the_list.append(node) return directions, the_list