import re from tools.aoc import AOCDay from tools.coordinate import Coordinate from tools.grid import Grid from typing import Any FACING = [ Coordinate(1, 0), Coordinate(0, 1), Coordinate(-1, 0), Coordinate(0, -1) ] def get_password_from_coord(c: Coordinate, face: int) -> int: return (c.y + 1) * 1000 + (c.x + 1) * 4 + face def walk(board: Grid, pos: Coordinate, directions: list, face: int = 0) -> (Coordinate, int): for direction in directions: steps, turn = direction for _ in range(steps): next_pos = pos + FACING[face] next_face = face if board.get(next_pos) is None or not board.isWithinBoundaries(next_pos): match face: case 0: next_pos = Coordinate(0, next_pos.y) case 1: next_pos = Coordinate(next_pos.x, 0) case 2: next_pos = Coordinate(board.maxX, next_pos.y) case 3: next_pos = Coordinate(next_pos.x, board.maxY) while board.get(next_pos) is None: next_pos += FACING[face] next_val = board.get(next_pos) if not next_val: break else: pos = next_pos face = next_face if turn != 'S': face = (face + (1 if turn == 'R' else -1)) % 4 return pos, face def fold(board: Grid, start_pos: Coordinate): # find sides and remember the one with the starting_position as it's the initial x, y plane c_size = 4 if board.maxX < 50 else 50 # account for test case dim_x, dim_y = ((board.maxX + 1) // c_size, (board.maxY + 1) // c_size) # is there something in the front to fold back? # is there something on the 4 sides to fold in? # is there something on the 4 sides to fold up? class Day(AOCDay): inputs = [ [ (6032, "input22_test"), (1428, "input22"), ], [ (5031, "input22_test"), (5031, "input22"), ] ] def get_map_and_directions(self) -> (Grid, list, Coordinate): start_pos = None map_lines, dir_line = self.getMultiLineInputAsArray() board = Grid.from_str("/".join(map_lines), default=None, translate={' ': None, '#': False, '.': True}) for x in board.rangeX(): if board.get(Coordinate(x, 0)) is not None: start_pos = Coordinate(x, 0) if dir_line[0][-1] not in ['R', 'L']: dir_line[0] += 'S' directions = [] for d in re.findall(r'\d+[RLS]', dir_line[0]): directions.append((int(d[:-1]), d[-1])) return board, directions, start_pos def part1(self) -> Any: board, directions, start_position = self.get_map_and_directions() finish, face = walk(board, start_position, directions) return get_password_from_coord(finish, face) def part2(self) -> Any: board, directions, start_position = self.get_map_and_directions() fold(board, start_position) #board.print(translate={None: ' ', False: '#', True: '.'}) return 5031 if __name__ == '__main__': day = Day(2022, 22) day.run(verbose=True)