diff --git a/2019/d20/ex1/ex1.py b/2019/d20/ex1/ex1.py new file mode 100755 index 0000000..fd37c03 --- /dev/null +++ b/2019/d20/ex1/ex1.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python + +import heapq +import sys +from collections import defaultdict +from typing import Iterator, NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +Graph = dict[Point, set[Point]] + + +def solve(input: str) -> int: + def post_process_gates( + letters: dict[Point, str], paths: set[Point] + ) -> dict[str, set[Point]]: + res: dict[str, set[Point]] = defaultdict(set) + for p1, first in letters.items(): + for dx, dy in ((0, 1), (1, 0)): + p2 = Point(p1.x + dx, p1.y + dy) + if p2 not in letters: + continue + gate = first + letters[p2] + p0 = Point(p1.x - dx, p1.y - dy) + p3 = Point(p2.x + dx, p2.y + dy) + res[gate] |= {p0, p3} & paths + return res + + def to_graph(paths: set[Point], gates: dict[str, set[Point]]) -> Graph: + res: dict[Point, set[Point]] = defaultdict(set) + + for p in paths: + res[p] |= set(p.neighbours()) & paths + + for gate, points in gates.items(): + if len(points) == 1: + assert gate in ("AA", "ZZ") # Sanity check + continue + for p in points: + res[p] |= points + res[p].remove(p) + + return res + + def parse(input: list[str]) -> tuple[Graph, Point, Point]: + letters: dict[Point, str] = {} + paths: set[Point] = set() + + for x, line in enumerate(input): + for y, c in enumerate(line): + if c == "#" or c == " ": + continue + p = Point(x, y) + if c == ".": + paths.add(p) + continue + letters[p] = c + + gates = post_process_gates(letters, paths) + graph = to_graph(paths, post_process_gates(letters, paths)) + return graph, next(iter(gates["AA"])), next(iter(gates["ZZ"])) + + def djikstra(start: Point, end: Point, graph: Graph) -> int: + # Priority queue of (distance, point) + queue = [(0, start)] + seen: set[Point] = set() + + while len(queue) > 0: + dist, p = heapq.heappop(queue) + if p == end: + return dist + # We must have seen p with a smaller distance before + if p in seen: + continue + # First time encountering p, must be the smallest distance to it + seen.add(p) + # Add all neighbours to be visited + for n in graph[p]: + heapq.heappush(queue, (dist + 1, n)) + + assert False # Sanity check + + graph, start, end = parse(input.splitlines()) + return djikstra(start, end, graph) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d20/ex1/input b/2019/d20/ex1/input new file mode 100644 index 0000000..093d3b3 --- /dev/null +++ b/2019/d20/ex1/input @@ -0,0 +1,115 @@ + A N N I K F W + P N A J D A L + ###############################.#######.#########.#########.#####.###.#.##################################### + #.#.#.#.#...#.....#...#.........#.....#.....#.....#.......#.....#.....#...#.#...#...#.#.............#.......# + #.#.#.#.###.#####.###.#########.#.###.#.#######.###.#.#####.#.###.###.#.#.#.#.#.#.###.#.#############.####### + #...............#.#...#...........#...#...#.....#...#.#.....#.#.#.#...#.#.....#...#.#.......#...#.#...#...#.# + #####.###.#####.#.###.###.###.#####.###.#####.#.#.#.###.#.###.#.###.#####.###.###.#.#.###.###.###.###.###.#.# + #.....#.#.#.#.....#.#.#.#...#.....#...#.....#.#.#.#...#.#.#...#.......#...#.#...#.#...#.......#.#.....#.#.#.# + #######.###.#####.#.#.#.#.#.#########.#.#######.#.###.#.#####.#.#########.#.#.#####.###.#.#.#.#.#.#####.#.#.# + #.#...............#.#.....#.#.....#...#.....#.......#.#...#...#.....#...#.#...#...#...#.#.#.#.........#.....# + #.#.###.#.###.###.#.#.#.#######.#.#.#####.###########.#####.#.#.#.#####.###.#.#.###.#######.###########.##### + #.#.#...#.#...#.#.....#.#.......#...#.....#...#.....#.#.....#.#.#.#.......#.#...........#.....#.#.#.#.#.....# + #.###########.#.#.#.###.#######.#######.#####.#.###.#.###.###.#.#########.###.#####.#.#.###.#.#.#.#.#.#.##### + #.#.....#...#.#...#...#.#.#...#...#.......#.......#...#...#...#.....#.............#.#.#.#...#.#.....#.#...#.# + #.#.###.###.#.#.###.###.#.###.#.#######.#########.###########.#.#.###.###.###.#####.###############.#.#.###.# + #.....#.#.#...#.#...#.....#.#.....#.#.#.....#.#...#.......#...#.#...#.#...#...#.#.#.....#...#.#...#...#.....# + ###.#####.###.#####.#######.#.#.###.#.###.###.#.#.###.#.#####.###.#######.###.#.#.#######.###.###.#.#####.### + #.........#...#.......#.......#.#.#...#.......#.#...#.#.....#.#.....#.....#.........#.#.#...#...#.......#...# + ###.#####.###.#.#.###.#.###.#.#.#.#.#########.#.#######.###.#.#.#######.#####.###.###.#.#.###.###.#####.#.#.# + #...#.#.#.#.#.#.#.#...#.#.#.#.#.......#.#.....#.#.#...#.#.#.#.#.#.#.#.....#.#.#.#.#.........#...#.#.#.#...#.# + ###.#.#.###.#######.#####.#.###.###.###.###.#.#.#.#.###.#.#.#.#.#.#.###.###.###.#####.#######.#####.#.###.### + #.....#...#...#.#.#.#.....#.#.....#.#.#.....#.#.....#.....#...#.....#...#.....#...#...#.....#.#...#.#.#.....# + ###.###.###.#.#.#.#######.#####.#####.###.#.###.#.#.#####.#####.#######.###.###.###.#.###.###.###.#.#.###.#.# + #.......#.#.#.....#.#.#.#...#.#...#.#.....#.#.#.#.#.#.#.#.#...#...#.#...............#.#.#...#.#.#.#.......#.# + ###.#####.###.###.#.#.#.#.###.#.###.###.#####.#.###.#.#.#.#.#.#.###.#.#.#####.#.#.#.###.#.###.#.#.#.#.#.##### + #.#...#.....#.#.#.................#.#...#.........#.#.#.#...#.#.....#.#.#...#.#.#.#.........#.#...#.#.#...#.# + #.#.###.###.###.###.#.#.#.#####.###.###.#######.#####.#.#.###.#####.#.#.#.#.#.#.#.#.#.#####.#.#.#.#####.#.#.# + #.#.....#...#.....#.#.#.#.#...........#...#.......#.......#.....#...#.#.#.#...#.#.#.#.#...#.#.#.#.#.#...#...# + #.#.#######.#####.###.###.#########.#####.#####.###########.#####.#.#####.#############.#####.###.#.###.##### + #.........#.#...#...#...#.# J T S F N W A #...#.#.#...#.#.#.....#.#.# + ###.#####.#####.#.######### R R E A N P P #.###.#.###.#.#.###.#.#.#.# + #...#.#.#...#.#...#...#...# #.#...#.......#...#.#.....# + ###.#.#.#####.###.###.#.### #.###.#####.#####.###.##### + #...#.#.#.#...#...#.#...#..HV #.#.#.#...#...#...#.#...#.# + #.#.#.#.#.###.###.#.###.#.# #.#.#.###.#.#####.#.#.###.# + #.#.......#.....#.....#...# #.#...#.#.........#.....#.# + #.###.#######.#.#.#.#.#.#.# #.#.#.#.#.#######.#.#.###.# + #.#...#.#...#.#.#.#.#.#.#.# QJ..#.#.#.#.......#...#...#..KV + #.#.###.#.###.###.#.###.### #.#.#.#.#.###.#########.#.# +FZ..#...............#.......# #...#.#.....#.#.....#...#..ZZ + #####.#.#.#####.###.#.##### #.###.#.#########.###.###.# +JR..#.#.#.#...#.#...#.#.#....HR #.#.#...#.....#.#.#.......# + #.#.#########.#########.### ###.#####.#####.#.######### + #...#.#.#.#.....#.#.......# IJ....#...#.............#.#.# + #.#.#.#.#.###.#.#.###.##### ###.#.#####.###.#.#.###.#.# + #.#...........#.......#.#.# #.....#.....#...#.#...#....SE + #########.###.#########.#.# ###.###.###.#######.###.### + #.......#...#.#.#...#.....# #.#.....#.....#.....#.....# + #.#.###########.#.#.#.#.### #.###.#.###########.#####.# + #.#...#.#...#.#.#.#...#...# #.#.#.#.#.....#...........# + #.#.###.#.###.#.#.#####.### #.#.#####.###############.# +AB..#.......#.........#.....# #.............#.........#.# + #####.###.###.#.#####.##### #.#.###.###.#######.#.#.### + #...#.#.......#...#........KV KD..#.#.#.#.......#.#.#.#...# + #.#########.###.###.#.#.### #.###.#####.###.#.###.#.### +QJ........#.#...#.#...#.#.#.# #.#.....#...#.#.....#.#...# + #.#.#.#.#.#.#########.###.# #.###.#######.###.#.#.#.#.# + #.#.#.#.#.#.#.#...#...#.#.# #.#.....#.#...#.#.#...#.#..YO + #####.#.#.###.#.#######.#.# #####.###.###.#.########### + #.....#...#.#...#.#........RF KR..........#................AX + #########.#.###.#.###.##### #.#.###.###.#.#.###.###.#.# + #.#...#...................# #.#.#.....#.#.#...#.#...#.# + #.###.#####.#.#.#.#.####### #.#####.###.#########.##### + #.........#.#.#.#.#.#.....# #.#.#.......#.#...#.#.#...# + ###.#.#########.#####.###.# ###.#.#######.#.###.###.### +KR....#.#.......#.#.#.#.#...# #.....#.....#.............# + #####.#.###.#####.#.#.#.### ###.#####.#.###.###.#.#.#.# + #.....#.#.....#.#...#.#....HM #.#...#.#.#.....#.#.#.#.#..XY + #.#####.#.#####.#.#.#.##### #.#####.#.#.#.###.#.###.### + #.......#.........#.....#.# AI..#.#.#...#.#.#.#.#.#.#...# + #################.###.#.#.# #.#.#.###.#.###.#.###.#.### + #...........#...#.#...#.#.# #.........#.#...#.#.....#.# + #.###.#.###.#.#.#.#.#####.# #.###.#########.#.#######.# + #.#.#.#...#...#.#.#.....#..ZW #.#...#.....#...#.....#....WP + #.#######.#.#############.# #######.#.#.#.#.#.#.#.#.### +AA......#...#.......#.....#.# XY....#...#.#...#...#.#.#...# + ###.#######.###.#.###.###.# ###.#.#####.#####.###.#.#.# +HV......#.#...#.#.#.........# #.#...#.........#.#.#.#.#.# + #######.#####.###.#.###.### #.#.#######.###.###.#.###.# +RF..#.#...#.#.#.#.#.#.#.#.#..KH #.....#.......#...#.......# + #.#.###.#.#.#.#.#####.###.# #.#######.#.###.#####.##### + #.#.....#.....#...#.....#.# #.#.#.....#.#.....#.......# + #.#.#.###.###.#.#.#.###.#.# #.#.#.#.#.#.###.#####.#.### + #...#.....#.#...#...#.....# #.#.#.#.#.#.#.......#.#...# + #####.#.#.#.#.#####.###.#.# A W N F Y U A ###.#####.#.###.#####.#.#.# + #.....#.#...#...#.....#.#.# B L A Z O E X #.#.#...#.#.#.#.#...#.#.#.# + ###.#.###.#######.#.#####.#######.###.#########.#######.#######.#####.#######.#####.#.#.###.###.#.###.#.#.### + #...#.#.....#.....#.....#.......#...#.#.......#.#.#.....#...#.#.....#...#.....#...........#...#.......#.#...# + #.###.###.#.###.#.###.###.#.#####.###.#.###.###.#.###.###.#.#.###.###.#.#.#####.###.#.#.#######.#####.####### + #.#.....#.#.#...#.#.....#.#.#.....#.....#...#...#.#.....#.#.#.......#.#.#.........#.#.#.#.#.......#.#.#.....# + #####.#####.#####.###.#.#########.#######.#.#.###.#####.#.#.#.#########.###.###.#.#.#####.###.#####.#.###.### + #.........#.#.....#...#.#.#.........#.....#.#.......#.....#.#.......#...#...#...#.#.......#.#.#.............# + #####.###.#######.#####.#.###.#####.#.#############.#######.#######.###.#.#####.#.###.###.#.#####.###.#####.# + #.......#.#...#.....#.......#.#.#.#.#.....#.#.......#.....#...#.#.....#.#.#...#.#.#.....#.....#...#.......#.# + #.###.#####.#.###.#.#.#.#######.#.#.###.###.#.#####.###.#.#.###.###.###.#.#.#########.#####.#.###.#.###.#.#.# + #.#.........#.#.#.#.#.#.#.....#.....#.......#.....#.#...#...#...#.#...#.#...........#.#.#.#.#...#.#.#.#.#.#.# + #.#.#.#.#.###.#.#############.###.#.#.#######.#####.#.###.###.###.#.###.#.#.#.#####.#.#.#.#.#########.#.##### + #.#.#.#.#...#.#.#.....#...#.#...#.#.#...#.........#.#.#.......#.....#...#.#.#.#.....#...#.#.......#.#.....#.# + #.#.#.#.#.#####.###.#####.#.#.#.###.#.#.#.#######.#.#.###.#.#####.###.###.###############.#.#######.#####.#.# + #.#.#.#.#.....#.........#.#.#.#.#...#.#.#.#.....#.#.#.#...#.#.......#.#...#.#.......#...#.#...#...#.........# + ###.#.#.###.###.#.#.###.#.#.###.#.###.#####.#.###.###.#############.#.###.#.#####.###.###.#.#####.#.#####.#.# + #...#.#.#.....#.#.#.#...............#.#...#.#.......#.........#.....#.#.#.......#.....#.#.........#.#.....#.# + #######################.#.#########.#.###.#####.###.#.###########.#.#.#.###.#####.#####.###.#########.#.###.# + #.#.......#.............#.#.#.......#.......#.#.#.#.#...#...#.....#.#...#.....#.#.#...#.#.#...#.....#.#...#.# + #.#####.#.###.#############.#.###.#####.#####.###.#.#.###.#####.#######.#.#####.#.###.#.#.#######.#####.#.#.# + #.......#.......#.........#.#.#.....#.......#.......#.#.#.#.#.#.......#.#.....#...#.#...#.#.....#.#.#...#.#.# + #.###.###.#.#.###########.#.#######.#.#####.#######.#.#.#.#.#.#####.#.#.###.#.###.#.#.#.#.#.#.#.#.#.###.##### + #...#.#...#.#.#.....#...#.....#...#.#.#.#...#...#...#.........#.....#.#.#...#...#.....#.....#.#.....#.#.....# + ###.###.###.#####.#####.#.###.#.###.#.#.#######.###.#.#.###.#.#####.###.#.#######.#####.#######.#####.#####.# + #...#...#...#...........#.#.........#.......#.....#.#.#.#...#.#.#.....#.#...#.#.#.#.#...#.....#.#.......#.#.# + #.#.###.###.#####.#####.#####.#########.###.###.###.#####.#####.###.###.###.#.#.#.#.#####.#.###.#.#.#.#.#.### + #.#.#...#.......#...#.............#.......#.#.......#.........#.....#.....#...............#...#...#.#.#.....# + #################################.###.#########.#######.#########.###.#######.############################### + H U H A Z K T + M E R I W H R diff --git a/2019/d20/ex2/ex2.py b/2019/d20/ex2/ex2.py new file mode 100755 index 0000000..79cc181 --- /dev/null +++ b/2019/d20/ex2/ex2.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +import enum +import heapq +import sys +from collections import defaultdict +from typing import Iterator, NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +class LevelDelta(enum.IntEnum): + PATH = 0 + INNER_GATE = 1 + OUTER_GATE = -1 + + +Graph = dict[Point, set[tuple[Point, LevelDelta]]] + + +def solve(input: str) -> int: + def post_process_gates( + letters: dict[Point, str], paths: set[Point] + ) -> dict[str, set[Point]]: + res: dict[str, set[Point]] = defaultdict(set) + for p1, first in letters.items(): + for dx, dy in ((0, 1), (1, 0)): + p2 = Point(p1.x + dx, p1.y + dy) + if p2 not in letters: + continue + gate = first + letters[p2] + p0 = Point(p1.x - dx, p1.y - dy) + p3 = Point(p2.x + dx, p2.y + dy) + res[gate] |= {p0, p3} & paths + return res + + def to_graph(paths: set[Point], gates: dict[str, set[Point]]) -> Graph: + res: dict[Point, set[tuple[Point, LevelDelta]]] = defaultdict(set) + + for p in paths: + res[p] |= {(n, LevelDelta.PATH) for n in p.neighbours() if n in paths} + + outer_x = {min(p.x for p in paths), max(p.x for p in paths)} + outer_y = {min(p.y for p in paths), max(p.y for p in paths)} + + for gate, points in gates.items(): + if len(points) == 1: + assert gate in ("AA", "ZZ") # Sanity check + continue + for p in points: + other = next(iter(other for other in points if other != p)) + delta = ( + LevelDelta.OUTER_GATE + if p.x in outer_x or p.y in outer_y + else LevelDelta.INNER_GATE + ) + res[p].add((other, delta)) + return res + + def parse(input: list[str]) -> tuple[Graph, Point, Point]: + letters: dict[Point, str] = {} + paths: set[Point] = set() + + for x, line in enumerate(input): + for y, c in enumerate(line): + if c == "#" or c == " ": + continue + p = Point(x, y) + if c == ".": + paths.add(p) + continue + letters[p] = c + + gates = post_process_gates(letters, paths) + graph = to_graph(paths, post_process_gates(letters, paths)) + return graph, next(iter(gates["AA"])), next(iter(gates["ZZ"])) + + def djikstra(start: Point, end: Point, graph: Graph) -> int: + # Priority queue of (distance, point, level) + queue = [(0, start, 0)] + seen: set[tuple[Point, int]] = set() + + while len(queue) > 0: + dist, p, level = heapq.heappop(queue) + if p == end and level == 0: + return dist + # We must have seen p at this level with a smaller distance before + if (p, level) in seen: + continue + # First time encountering p at this level, must be the smallest distance to it + seen.add((p, level)) + # Add all neighbours to be visited + for n, delta in graph[p]: + n_level = level + delta + # Don't attempt to go out when at the most outer level + if n_level < 0: + continue + heapq.heappush(queue, (dist + 1, n, n_level)) + + assert False # Sanity check + + graph, start, end = parse(input.splitlines()) + return djikstra(start, end, graph) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d20/ex2/input b/2019/d20/ex2/input new file mode 100644 index 0000000..093d3b3 --- /dev/null +++ b/2019/d20/ex2/input @@ -0,0 +1,115 @@ + A N N I K F W + P N A J D A L + ###############################.#######.#########.#########.#####.###.#.##################################### + #.#.#.#.#...#.....#...#.........#.....#.....#.....#.......#.....#.....#...#.#...#...#.#.............#.......# + #.#.#.#.###.#####.###.#########.#.###.#.#######.###.#.#####.#.###.###.#.#.#.#.#.#.###.#.#############.####### + #...............#.#...#...........#...#...#.....#...#.#.....#.#.#.#...#.#.....#...#.#.......#...#.#...#...#.# + #####.###.#####.#.###.###.###.#####.###.#####.#.#.#.###.#.###.#.###.#####.###.###.#.#.###.###.###.###.###.#.# + #.....#.#.#.#.....#.#.#.#...#.....#...#.....#.#.#.#...#.#.#...#.......#...#.#...#.#...#.......#.#.....#.#.#.# + #######.###.#####.#.#.#.#.#.#########.#.#######.#.###.#.#####.#.#########.#.#.#####.###.#.#.#.#.#.#####.#.#.# + #.#...............#.#.....#.#.....#...#.....#.......#.#...#...#.....#...#.#...#...#...#.#.#.#.........#.....# + #.#.###.#.###.###.#.#.#.#######.#.#.#####.###########.#####.#.#.#.#####.###.#.#.###.#######.###########.##### + #.#.#...#.#...#.#.....#.#.......#...#.....#...#.....#.#.....#.#.#.#.......#.#...........#.....#.#.#.#.#.....# + #.###########.#.#.#.###.#######.#######.#####.#.###.#.###.###.#.#########.###.#####.#.#.###.#.#.#.#.#.#.##### + #.#.....#...#.#...#...#.#.#...#...#.......#.......#...#...#...#.....#.............#.#.#.#...#.#.....#.#...#.# + #.#.###.###.#.#.###.###.#.###.#.#######.#########.###########.#.#.###.###.###.#####.###############.#.#.###.# + #.....#.#.#...#.#...#.....#.#.....#.#.#.....#.#...#.......#...#.#...#.#...#...#.#.#.....#...#.#...#...#.....# + ###.#####.###.#####.#######.#.#.###.#.###.###.#.#.###.#.#####.###.#######.###.#.#.#######.###.###.#.#####.### + #.........#...#.......#.......#.#.#...#.......#.#...#.#.....#.#.....#.....#.........#.#.#...#...#.......#...# + ###.#####.###.#.#.###.#.###.#.#.#.#.#########.#.#######.###.#.#.#######.#####.###.###.#.#.###.###.#####.#.#.# + #...#.#.#.#.#.#.#.#...#.#.#.#.#.......#.#.....#.#.#...#.#.#.#.#.#.#.#.....#.#.#.#.#.........#...#.#.#.#...#.# + ###.#.#.###.#######.#####.#.###.###.###.###.#.#.#.#.###.#.#.#.#.#.#.###.###.###.#####.#######.#####.#.###.### + #.....#...#...#.#.#.#.....#.#.....#.#.#.....#.#.....#.....#...#.....#...#.....#...#...#.....#.#...#.#.#.....# + ###.###.###.#.#.#.#######.#####.#####.###.#.###.#.#.#####.#####.#######.###.###.###.#.###.###.###.#.#.###.#.# + #.......#.#.#.....#.#.#.#...#.#...#.#.....#.#.#.#.#.#.#.#.#...#...#.#...............#.#.#...#.#.#.#.......#.# + ###.#####.###.###.#.#.#.#.###.#.###.###.#####.#.###.#.#.#.#.#.#.###.#.#.#####.#.#.#.###.#.###.#.#.#.#.#.##### + #.#...#.....#.#.#.................#.#...#.........#.#.#.#...#.#.....#.#.#...#.#.#.#.........#.#...#.#.#...#.# + #.#.###.###.###.###.#.#.#.#####.###.###.#######.#####.#.#.###.#####.#.#.#.#.#.#.#.#.#.#####.#.#.#.#####.#.#.# + #.#.....#...#.....#.#.#.#.#...........#...#.......#.......#.....#...#.#.#.#...#.#.#.#.#...#.#.#.#.#.#...#...# + #.#.#######.#####.###.###.#########.#####.#####.###########.#####.#.#####.#############.#####.###.#.###.##### + #.........#.#...#...#...#.# J T S F N W A #...#.#.#...#.#.#.....#.#.# + ###.#####.#####.#.######### R R E A N P P #.###.#.###.#.#.###.#.#.#.# + #...#.#.#...#.#...#...#...# #.#...#.......#...#.#.....# + ###.#.#.#####.###.###.#.### #.###.#####.#####.###.##### + #...#.#.#.#...#...#.#...#..HV #.#.#.#...#...#...#.#...#.# + #.#.#.#.#.###.###.#.###.#.# #.#.#.###.#.#####.#.#.###.# + #.#.......#.....#.....#...# #.#...#.#.........#.....#.# + #.###.#######.#.#.#.#.#.#.# #.#.#.#.#.#######.#.#.###.# + #.#...#.#...#.#.#.#.#.#.#.# QJ..#.#.#.#.......#...#...#..KV + #.#.###.#.###.###.#.###.### #.#.#.#.#.###.#########.#.# +FZ..#...............#.......# #...#.#.....#.#.....#...#..ZZ + #####.#.#.#####.###.#.##### #.###.#.#########.###.###.# +JR..#.#.#.#...#.#...#.#.#....HR #.#.#...#.....#.#.#.......# + #.#.#########.#########.### ###.#####.#####.#.######### + #...#.#.#.#.....#.#.......# IJ....#...#.............#.#.# + #.#.#.#.#.###.#.#.###.##### ###.#.#####.###.#.#.###.#.# + #.#...........#.......#.#.# #.....#.....#...#.#...#....SE + #########.###.#########.#.# ###.###.###.#######.###.### + #.......#...#.#.#...#.....# #.#.....#.....#.....#.....# + #.#.###########.#.#.#.#.### #.###.#.###########.#####.# + #.#...#.#...#.#.#.#...#...# #.#.#.#.#.....#...........# + #.#.###.#.###.#.#.#####.### #.#.#####.###############.# +AB..#.......#.........#.....# #.............#.........#.# + #####.###.###.#.#####.##### #.#.###.###.#######.#.#.### + #...#.#.......#...#........KV KD..#.#.#.#.......#.#.#.#...# + #.#########.###.###.#.#.### #.###.#####.###.#.###.#.### +QJ........#.#...#.#...#.#.#.# #.#.....#...#.#.....#.#...# + #.#.#.#.#.#.#########.###.# #.###.#######.###.#.#.#.#.# + #.#.#.#.#.#.#.#...#...#.#.# #.#.....#.#...#.#.#...#.#..YO + #####.#.#.###.#.#######.#.# #####.###.###.#.########### + #.....#...#.#...#.#........RF KR..........#................AX + #########.#.###.#.###.##### #.#.###.###.#.#.###.###.#.# + #.#...#...................# #.#.#.....#.#.#...#.#...#.# + #.###.#####.#.#.#.#.####### #.#####.###.#########.##### + #.........#.#.#.#.#.#.....# #.#.#.......#.#...#.#.#...# + ###.#.#########.#####.###.# ###.#.#######.#.###.###.### +KR....#.#.......#.#.#.#.#...# #.....#.....#.............# + #####.#.###.#####.#.#.#.### ###.#####.#.###.###.#.#.#.# + #.....#.#.....#.#...#.#....HM #.#...#.#.#.....#.#.#.#.#..XY + #.#####.#.#####.#.#.#.##### #.#####.#.#.#.###.#.###.### + #.......#.........#.....#.# AI..#.#.#...#.#.#.#.#.#.#...# + #################.###.#.#.# #.#.#.###.#.###.#.###.#.### + #...........#...#.#...#.#.# #.........#.#...#.#.....#.# + #.###.#.###.#.#.#.#.#####.# #.###.#########.#.#######.# + #.#.#.#...#...#.#.#.....#..ZW #.#...#.....#...#.....#....WP + #.#######.#.#############.# #######.#.#.#.#.#.#.#.#.### +AA......#...#.......#.....#.# XY....#...#.#...#...#.#.#...# + ###.#######.###.#.###.###.# ###.#.#####.#####.###.#.#.# +HV......#.#...#.#.#.........# #.#...#.........#.#.#.#.#.# + #######.#####.###.#.###.### #.#.#######.###.###.#.###.# +RF..#.#...#.#.#.#.#.#.#.#.#..KH #.....#.......#...#.......# + #.#.###.#.#.#.#.#####.###.# #.#######.#.###.#####.##### + #.#.....#.....#...#.....#.# #.#.#.....#.#.....#.......# + #.#.#.###.###.#.#.#.###.#.# #.#.#.#.#.#.###.#####.#.### + #...#.....#.#...#...#.....# #.#.#.#.#.#.#.......#.#...# + #####.#.#.#.#.#####.###.#.# A W N F Y U A ###.#####.#.###.#####.#.#.# + #.....#.#...#...#.....#.#.# B L A Z O E X #.#.#...#.#.#.#.#...#.#.#.# + ###.#.###.#######.#.#####.#######.###.#########.#######.#######.#####.#######.#####.#.#.###.###.#.###.#.#.### + #...#.#.....#.....#.....#.......#...#.#.......#.#.#.....#...#.#.....#...#.....#...........#...#.......#.#...# + #.###.###.#.###.#.###.###.#.#####.###.#.###.###.#.###.###.#.#.###.###.#.#.#####.###.#.#.#######.#####.####### + #.#.....#.#.#...#.#.....#.#.#.....#.....#...#...#.#.....#.#.#.......#.#.#.........#.#.#.#.#.......#.#.#.....# + #####.#####.#####.###.#.#########.#######.#.#.###.#####.#.#.#.#########.###.###.#.#.#####.###.#####.#.###.### + #.........#.#.....#...#.#.#.........#.....#.#.......#.....#.#.......#...#...#...#.#.......#.#.#.............# + #####.###.#######.#####.#.###.#####.#.#############.#######.#######.###.#.#####.#.###.###.#.#####.###.#####.# + #.......#.#...#.....#.......#.#.#.#.#.....#.#.......#.....#...#.#.....#.#.#...#.#.#.....#.....#...#.......#.# + #.###.#####.#.###.#.#.#.#######.#.#.###.###.#.#####.###.#.#.###.###.###.#.#.#########.#####.#.###.#.###.#.#.# + #.#.........#.#.#.#.#.#.#.....#.....#.......#.....#.#...#...#...#.#...#.#...........#.#.#.#.#...#.#.#.#.#.#.# + #.#.#.#.#.###.#.#############.###.#.#.#######.#####.#.###.###.###.#.###.#.#.#.#####.#.#.#.#.#########.#.##### + #.#.#.#.#...#.#.#.....#...#.#...#.#.#...#.........#.#.#.......#.....#...#.#.#.#.....#...#.#.......#.#.....#.# + #.#.#.#.#.#####.###.#####.#.#.#.###.#.#.#.#######.#.#.###.#.#####.###.###.###############.#.#######.#####.#.# + #.#.#.#.#.....#.........#.#.#.#.#...#.#.#.#.....#.#.#.#...#.#.......#.#...#.#.......#...#.#...#...#.........# + ###.#.#.###.###.#.#.###.#.#.###.#.###.#####.#.###.###.#############.#.###.#.#####.###.###.#.#####.#.#####.#.# + #...#.#.#.....#.#.#.#...............#.#...#.#.......#.........#.....#.#.#.......#.....#.#.........#.#.....#.# + #######################.#.#########.#.###.#####.###.#.###########.#.#.#.###.#####.#####.###.#########.#.###.# + #.#.......#.............#.#.#.......#.......#.#.#.#.#...#...#.....#.#...#.....#.#.#...#.#.#...#.....#.#...#.# + #.#####.#.###.#############.#.###.#####.#####.###.#.#.###.#####.#######.#.#####.#.###.#.#.#######.#####.#.#.# + #.......#.......#.........#.#.#.....#.......#.......#.#.#.#.#.#.......#.#.....#...#.#...#.#.....#.#.#...#.#.# + #.###.###.#.#.###########.#.#######.#.#####.#######.#.#.#.#.#.#####.#.#.###.#.###.#.#.#.#.#.#.#.#.#.###.##### + #...#.#...#.#.#.....#...#.....#...#.#.#.#...#...#...#.........#.....#.#.#...#...#.....#.....#.#.....#.#.....# + ###.###.###.#####.#####.#.###.#.###.#.#.#######.###.#.#.###.#.#####.###.#.#######.#####.#######.#####.#####.# + #...#...#...#...........#.#.........#.......#.....#.#.#.#...#.#.#.....#.#...#.#.#.#.#...#.....#.#.......#.#.# + #.#.###.###.#####.#####.#####.#########.###.###.###.#####.#####.###.###.###.#.#.#.#.#####.#.###.#.#.#.#.#.### + #.#.#...#.......#...#.............#.......#.#.......#.........#.....#.....#...............#...#...#.#.#.....# + #################################.###.#########.#######.#########.###.#######.############################### + H U H A Z K T + M E R I W H R diff --git a/2019/d21/ex1/ex1.py b/2019/d21/ex1/ex1.py new file mode 100755 index 0000000..a49688b --- /dev/null +++ b/2019/d21/ex1/ex1.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python + +import sys +from dataclasses import dataclass, field +from enum import IntEnum +from typing import List, NamedTuple + + +class ParameterMode(IntEnum): + POSITION = 0 # Acts on address + IMMEDIATE = 1 # Acts on the immediate value + RELATIVE = 2 # Acts on offset to relative base + + +class Instruction(NamedTuple): + address: int # The address of the instruction, for convenience + op: int # The opcode + p1_mode: ParameterMode # Which mode is the first parameter in + p2_mode: ParameterMode # Which mode is the second parameter in + p3_mode: ParameterMode # Which mode is the third parameter in + + +def lookup_ops(index: int, memory: List[int]) -> Instruction: + digits = list(map(int, str(memory[index]))) + a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values + return Instruction( + address=index, + op=d * 10 + e, + p1_mode=ParameterMode(c), + p2_mode=ParameterMode(b), + p3_mode=ParameterMode(a), + ) + + +class InputInterrupt(Exception): + pass + + +class OutputInterrupt(Exception): + pass + + +@dataclass +class Computer: + memory: List[int] # Memory space + rip: int = 0 # Instruction pointer + input_list: List[int] = field(default_factory=list) + output_list: List[int] = field(default_factory=list) + is_halted: bool = field(default=False, init=False) + relative_base: int = field(default=0, init=False) + + def run(self) -> None: + while not self.is_halted: + self.run_single() + + def run_no_output_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_single() + except OutputInterrupt: + continue + + def run_single(self) -> None: # Returns True when halted + instr = lookup_ops(self.rip, self.memory) + if instr.op == 99: # Halt + self.is_halted = True + elif instr.op == 1: # Sum + self._do_addition(instr) + elif instr.op == 2: # Multiplication + self._do_multiplication(instr) + elif instr.op == 3: # Load from input + self._do_input(instr) + elif instr.op == 4: # Store to output + self._do_output(instr) + elif instr.op == 5: # Jump if true + self._do_jump_if_true(instr) + elif instr.op == 6: # Jump if false + self._do_jump_if_false(instr) + elif instr.op == 7: # Less than + self._do_less_than(instr) + elif instr.op == 8: # Equal to + self._do_equal_to(instr) + elif instr.op == 9: # Change relative base + self._do_change_relative_base(instr) + else: + assert False # Sanity check + + def _fill_to_addres(self, address: int) -> None: + values = address - len(self.memory) + 1 + if values <= 0: + return + for __ in range(values): + self.memory.append(0) + + def _get_value(self, mode: ParameterMode, val: int) -> int: + if mode == ParameterMode.POSITION: + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + elif mode == ParameterMode.RELATIVE: + val += self.relative_base + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + assert mode == ParameterMode.IMMEDIATE # Sanity check + return val + + def _set_value(self, mode: ParameterMode, address: int, value: int) -> None: + if mode == ParameterMode.RELATIVE: + address += self.relative_base + else: + assert mode == ParameterMode.POSITION # Sanity check + + assert address >= 0 # Sanity check + self._fill_to_addres(address) + + self.memory[address] = value + + def _do_addition(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs + rhs) + + self.rip += 4 # Length of the instruction + + def _do_multiplication(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs * rhs) + + self.rip += 4 # Length of the instruction + + def _do_input(self, instr: Instruction) -> None: + if len(self.input_list) == 0: + raise InputInterrupt # No input, halt until an input is provided + + value = int(self.input_list.pop(0)) + param = self.memory[instr.address + 1] + + self._set_value(instr.p1_mode, param, value) + + self.rip += 2 # Length of the instruction + + def _do_output(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.output_list.append(value) + + self.rip += 2 # Length of the instruction + raise OutputInterrupt # Alert that we got an output to give + + def _do_jump_if_true(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond != 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_jump_if_false(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond == 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_less_than(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_equal_to(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_change_relative_base(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.relative_base += value + self.rip += 2 # Length of the instruction + + +def main() -> None: + memory = [int(n) for n in sys.stdin.read().split(",")] + springdroid = Computer(memory) + + script = "\n".join( + [ + # J = B is a hole + "NOT B J", + # T = C is a hole + "NOT C T", + # J = B or C is a hole + "OR T J", + # J = (B or C is a hole) AND (D is ground) + "AND D J", + # T = A is a hole + "NOT A T", + # J = ((B or C is a hole) AND (D is ground)) OR (A is a hole) + "OR T J", + "WALK", + "", # Final newline + ] + ) + + # Input our script + springdroid.input_list.extend(ord(c) for c in script) + springdroid.run_no_output_interrupt() + print(springdroid.output_list[-1]) + + +if __name__ == "__main__": + main() diff --git a/2019/d21/ex1/input b/2019/d21/ex1/input new file mode 100644 index 0000000..5da8bee --- /dev/null +++ b/2019/d21/ex1/input @@ -0,0 +1 @@ +109,2050,21102,1,966,1,21102,1,13,0,1106,0,1378,21101,0,20,0,1106,0,1337,21101,0,27,0,1106,0,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21101,0,1041,1,21102,1,73,0,1106,0,1421,21102,78,1,1,21101,0,1041,2,21102,1,88,0,1106,0,1301,21101,0,68,1,21101,1041,0,2,21101,103,0,0,1106,0,1301,1102,1,1,750,1105,1,298,21102,1,82,1,21102,1041,1,2,21101,0,125,0,1105,1,1301,1102,1,2,750,1105,1,298,21102,79,1,1,21102,1041,1,2,21101,147,0,0,1106,0,1301,21101,84,0,1,21101,0,1041,2,21102,162,1,0,1106,0,1301,1102,1,3,750,1105,1,298,21102,65,1,1,21102,1041,1,2,21101,184,0,0,1105,1,1301,21102,1,76,1,21101,1041,0,2,21102,199,1,0,1106,0,1301,21102,1,75,1,21101,0,1041,2,21101,0,214,0,1105,1,1301,21102,1,221,0,1105,1,1337,21101,10,0,1,21101,0,1041,2,21101,0,236,0,1106,0,1301,1106,0,553,21101,0,85,1,21101,1041,0,2,21102,1,254,0,1106,0,1301,21102,78,1,1,21102,1,1041,2,21101,0,269,0,1105,1,1301,21102,276,1,0,1106,0,1337,21102,10,1,1,21102,1,1041,2,21102,291,1,0,1106,0,1301,1101,1,0,755,1106,0,553,21101,32,0,1,21101,0,1041,2,21102,1,313,0,1105,1,1301,21101,0,320,0,1105,1,1337,21101,327,0,0,1106,0,1279,1202,1,1,749,21102,65,1,2,21102,73,1,3,21102,346,1,0,1105,1,1889,1206,1,367,1007,749,69,748,1005,748,360,1101,0,1,756,1001,749,-64,751,1105,1,406,1008,749,74,748,1006,748,381,1101,-1,0,751,1106,0,406,1008,749,84,748,1006,748,395,1102,1,-2,751,1105,1,406,21101,0,1100,1,21102,1,406,0,1105,1,1421,21102,1,32,1,21102,1100,1,2,21101,421,0,0,1106,0,1301,21101,428,0,0,1106,0,1337,21102,435,1,0,1106,0,1279,1202,1,1,749,1008,749,74,748,1006,748,453,1101,0,-1,752,1105,1,478,1008,749,84,748,1006,748,467,1102,1,-2,752,1106,0,478,21101,0,1168,1,21101,478,0,0,1106,0,1421,21101,0,485,0,1106,0,1337,21102,10,1,1,21102,1,1168,2,21102,500,1,0,1105,1,1301,1007,920,15,748,1005,748,518,21102,1,1209,1,21101,518,0,0,1105,1,1421,1002,920,3,529,1001,529,921,529,101,0,750,0,1001,529,1,537,102,1,751,0,1001,537,1,545,1002,752,1,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21102,1100,1,1,21102,1,570,0,1106,0,1421,21101,0,987,1,1105,1,581,21101,0,1001,1,21101,588,0,0,1106,0,1378,1101,758,0,593,1001,0,0,753,1006,753,654,20101,0,753,1,21101,610,0,0,1106,0,667,21102,1,0,1,21101,621,0,0,1105,1,1463,1205,1,647,21102,1015,1,1,21101,0,635,0,1106,0,1378,21102,1,1,1,21102,1,646,0,1105,1,1463,99,1001,593,1,593,1106,0,592,1006,755,664,1102,0,1,755,1106,0,647,4,754,99,109,2,1101,0,726,757,22101,0,-1,1,21102,9,1,2,21101,697,0,3,21101,0,692,0,1106,0,1913,109,-2,2106,0,0,109,2,101,0,757,706,1201,-1,0,0,1001,757,1,757,109,-2,2106,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,191,223,127,159,95,0,170,122,102,166,184,142,77,113,215,202,162,219,154,231,92,123,197,247,85,87,138,181,174,55,185,153,234,107,254,124,249,84,139,233,213,226,115,246,228,99,34,121,118,163,137,54,169,57,106,46,38,125,189,119,51,103,175,79,157,61,207,221,71,251,238,178,86,78,232,47,187,203,253,248,136,94,69,201,190,205,117,227,156,98,177,42,100,204,114,200,188,76,35,49,252,236,196,206,70,143,182,62,198,168,229,68,93,230,60,183,243,199,237,43,140,244,155,222,126,241,216,214,58,218,217,50,239,141,56,158,171,109,235,245,179,152,101,59,116,108,212,250,120,111,173,172,39,242,220,167,186,53,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,20102,1,1262,0,109,-1,2105,1,0,109,1,21102,1288,1,0,1106,0,1263,20102,1,1262,0,1101,0,0,1262,109,-1,2106,0,0,109,5,21101,0,1310,0,1106,0,1279,22102,1,1,-2,22208,-2,-4,-1,1205,-1,1332,21202,-3,1,1,21101,0,1332,0,1106,0,1421,109,-5,2105,1,0,109,2,21101,1346,0,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1105,1,1373,21102,1370,1,0,1105,1,1279,1105,1,1339,109,-2,2105,1,0,109,5,1202,-4,1,1385,21002,0,1,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1105,1,1396,109,-5,2105,1,0,109,2,104,10,21202,-1,1,1,21102,1436,1,0,1106,0,1378,104,10,99,109,-2,2105,1,0,109,3,20002,593,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2106,0,0,109,10,21101,0,5,-5,21102,1,1,-4,21101,0,0,-3,1206,-9,1555,21101,3,0,-6,21102,1,5,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1106,0,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1105,1,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21101,0,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21101,1,0,-9,1105,1,1689,1201,-5,716,1588,21001,0,0,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,22102,1,-5,1,21101,0,1613,0,1105,1,1444,1206,-1,1634,21202,-5,1,1,21102,1,1627,0,1106,0,1694,1206,1,1634,21102,2,1,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1105,1,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,0,1,-4,1105,1,1477,109,-10,2106,0,0,109,11,21101,0,0,-6,21101,0,0,-8,21102,0,1,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1724,21002,0,1,-5,1001,1724,1,1733,20101,0,0,-4,22101,0,-4,1,21101,0,1,2,21102,1,9,3,21102,1754,1,0,1105,1,1889,1206,1,1772,2201,-10,-4,1766,1001,1766,716,1766,21001,0,0,-3,1106,0,1790,21208,-4,-1,-9,1206,-9,1786,22101,0,-8,-3,1105,1,1790,21202,-7,1,-3,1001,1733,1,1796,20102,1,0,-2,21208,-2,-1,-9,1206,-9,1812,22102,1,-8,-1,1106,0,1816,22102,1,-7,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1105,1,1855,21208,-2,-1,-9,1206,-9,1869,22102,1,-1,-8,1105,1,1873,21201,-1,0,-7,21201,-6,1,-6,1105,1,1708,22101,0,-8,-10,109,-11,2106,0,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2106,0,0,0,109,5,1202,-2,1,1912,21207,-4,0,-1,1206,-1,1930,21101,0,0,-4,21201,-4,0,1,22102,1,-3,2,21102,1,1,3,21102,1,1949,0,1106,0,1954,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,22102,1,-5,-5,1106,0,2045,21201,-5,0,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1106,0,1954,21201,1,0,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2015,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,21202,-2,1,1,21101,0,2037,0,105,1,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2105,1,0 diff --git a/2019/d21/ex2/ex2.py b/2019/d21/ex2/ex2.py new file mode 100755 index 0000000..16d758a --- /dev/null +++ b/2019/d21/ex2/ex2.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python + +import sys +from dataclasses import dataclass, field +from enum import IntEnum +from typing import List, NamedTuple + + +class ParameterMode(IntEnum): + POSITION = 0 # Acts on address + IMMEDIATE = 1 # Acts on the immediate value + RELATIVE = 2 # Acts on offset to relative base + + +class Instruction(NamedTuple): + address: int # The address of the instruction, for convenience + op: int # The opcode + p1_mode: ParameterMode # Which mode is the first parameter in + p2_mode: ParameterMode # Which mode is the second parameter in + p3_mode: ParameterMode # Which mode is the third parameter in + + +def lookup_ops(index: int, memory: List[int]) -> Instruction: + digits = list(map(int, str(memory[index]))) + a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values + return Instruction( + address=index, + op=d * 10 + e, + p1_mode=ParameterMode(c), + p2_mode=ParameterMode(b), + p3_mode=ParameterMode(a), + ) + + +class InputInterrupt(Exception): + pass + + +class OutputInterrupt(Exception): + pass + + +@dataclass +class Computer: + memory: List[int] # Memory space + rip: int = 0 # Instruction pointer + input_list: List[int] = field(default_factory=list) + output_list: List[int] = field(default_factory=list) + is_halted: bool = field(default=False, init=False) + relative_base: int = field(default=0, init=False) + + def run(self) -> None: + while not self.is_halted: + self.run_single() + + def run_no_output_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_single() + except OutputInterrupt: + continue + + def run_single(self) -> None: # Returns True when halted + instr = lookup_ops(self.rip, self.memory) + if instr.op == 99: # Halt + self.is_halted = True + elif instr.op == 1: # Sum + self._do_addition(instr) + elif instr.op == 2: # Multiplication + self._do_multiplication(instr) + elif instr.op == 3: # Load from input + self._do_input(instr) + elif instr.op == 4: # Store to output + self._do_output(instr) + elif instr.op == 5: # Jump if true + self._do_jump_if_true(instr) + elif instr.op == 6: # Jump if false + self._do_jump_if_false(instr) + elif instr.op == 7: # Less than + self._do_less_than(instr) + elif instr.op == 8: # Equal to + self._do_equal_to(instr) + elif instr.op == 9: # Change relative base + self._do_change_relative_base(instr) + else: + assert False # Sanity check + + def _fill_to_addres(self, address: int) -> None: + values = address - len(self.memory) + 1 + if values <= 0: + return + for __ in range(values): + self.memory.append(0) + + def _get_value(self, mode: ParameterMode, val: int) -> int: + if mode == ParameterMode.POSITION: + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + elif mode == ParameterMode.RELATIVE: + val += self.relative_base + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + assert mode == ParameterMode.IMMEDIATE # Sanity check + return val + + def _set_value(self, mode: ParameterMode, address: int, value: int) -> None: + if mode == ParameterMode.RELATIVE: + address += self.relative_base + else: + assert mode == ParameterMode.POSITION # Sanity check + + assert address >= 0 # Sanity check + self._fill_to_addres(address) + + self.memory[address] = value + + def _do_addition(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs + rhs) + + self.rip += 4 # Length of the instruction + + def _do_multiplication(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs * rhs) + + self.rip += 4 # Length of the instruction + + def _do_input(self, instr: Instruction) -> None: + if len(self.input_list) == 0: + raise InputInterrupt # No input, halt until an input is provided + + value = int(self.input_list.pop(0)) + param = self.memory[instr.address + 1] + + self._set_value(instr.p1_mode, param, value) + + self.rip += 2 # Length of the instruction + + def _do_output(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.output_list.append(value) + + self.rip += 2 # Length of the instruction + raise OutputInterrupt # Alert that we got an output to give + + def _do_jump_if_true(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond != 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_jump_if_false(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond == 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_less_than(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_equal_to(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_change_relative_base(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.relative_base += value + self.rip += 2 # Length of the instruction + + +def main() -> None: + memory = [int(n) for n in sys.stdin.read().split(",")] + springdroid = Computer(memory) + + script = "\n".join( + [ + # J = B is a hole + "NOT B J", + # T = C is a hole + "NOT C T", + # J = B or C is a hole + "OR T J", + # J = (B or C is a hole) AND (D is ground) + "AND D J", + # J = (B or C is a hole) AND (D and H are ground) + "AND H J", + # T = A is a hole + "NOT A T", + # J = ((B or C is a hole) AND (D and H are ground)) OR (A is a hole) + "OR T J", + "RUN", + "", # Final newline + ] + ) + + # Input our script + springdroid.input_list.extend(ord(c) for c in script) + springdroid.run_no_output_interrupt() + print(springdroid.output_list[-1]) + + +if __name__ == "__main__": + main() diff --git a/2019/d21/ex2/input b/2019/d21/ex2/input new file mode 100644 index 0000000..5da8bee --- /dev/null +++ b/2019/d21/ex2/input @@ -0,0 +1 @@ +109,2050,21102,1,966,1,21102,1,13,0,1106,0,1378,21101,0,20,0,1106,0,1337,21101,0,27,0,1106,0,1279,1208,1,65,748,1005,748,73,1208,1,79,748,1005,748,110,1208,1,78,748,1005,748,132,1208,1,87,748,1005,748,169,1208,1,82,748,1005,748,239,21101,0,1041,1,21102,1,73,0,1106,0,1421,21102,78,1,1,21101,0,1041,2,21102,1,88,0,1106,0,1301,21101,0,68,1,21101,1041,0,2,21101,103,0,0,1106,0,1301,1102,1,1,750,1105,1,298,21102,1,82,1,21102,1041,1,2,21101,0,125,0,1105,1,1301,1102,1,2,750,1105,1,298,21102,79,1,1,21102,1041,1,2,21101,147,0,0,1106,0,1301,21101,84,0,1,21101,0,1041,2,21102,162,1,0,1106,0,1301,1102,1,3,750,1105,1,298,21102,65,1,1,21102,1041,1,2,21101,184,0,0,1105,1,1301,21102,1,76,1,21101,1041,0,2,21102,199,1,0,1106,0,1301,21102,1,75,1,21101,0,1041,2,21101,0,214,0,1105,1,1301,21102,1,221,0,1105,1,1337,21101,10,0,1,21101,0,1041,2,21101,0,236,0,1106,0,1301,1106,0,553,21101,0,85,1,21101,1041,0,2,21102,1,254,0,1106,0,1301,21102,78,1,1,21102,1,1041,2,21101,0,269,0,1105,1,1301,21102,276,1,0,1106,0,1337,21102,10,1,1,21102,1,1041,2,21102,291,1,0,1106,0,1301,1101,1,0,755,1106,0,553,21101,32,0,1,21101,0,1041,2,21102,1,313,0,1105,1,1301,21101,0,320,0,1105,1,1337,21101,327,0,0,1106,0,1279,1202,1,1,749,21102,65,1,2,21102,73,1,3,21102,346,1,0,1105,1,1889,1206,1,367,1007,749,69,748,1005,748,360,1101,0,1,756,1001,749,-64,751,1105,1,406,1008,749,74,748,1006,748,381,1101,-1,0,751,1106,0,406,1008,749,84,748,1006,748,395,1102,1,-2,751,1105,1,406,21101,0,1100,1,21102,1,406,0,1105,1,1421,21102,1,32,1,21102,1100,1,2,21101,421,0,0,1106,0,1301,21101,428,0,0,1106,0,1337,21102,435,1,0,1106,0,1279,1202,1,1,749,1008,749,74,748,1006,748,453,1101,0,-1,752,1105,1,478,1008,749,84,748,1006,748,467,1102,1,-2,752,1106,0,478,21101,0,1168,1,21101,478,0,0,1106,0,1421,21101,0,485,0,1106,0,1337,21102,10,1,1,21102,1,1168,2,21102,500,1,0,1105,1,1301,1007,920,15,748,1005,748,518,21102,1,1209,1,21101,518,0,0,1105,1,1421,1002,920,3,529,1001,529,921,529,101,0,750,0,1001,529,1,537,102,1,751,0,1001,537,1,545,1002,752,1,0,1001,920,1,920,1105,1,13,1005,755,577,1006,756,570,21102,1100,1,1,21102,1,570,0,1106,0,1421,21101,0,987,1,1105,1,581,21101,0,1001,1,21101,588,0,0,1106,0,1378,1101,758,0,593,1001,0,0,753,1006,753,654,20101,0,753,1,21101,610,0,0,1106,0,667,21102,1,0,1,21101,621,0,0,1105,1,1463,1205,1,647,21102,1015,1,1,21101,0,635,0,1106,0,1378,21102,1,1,1,21102,1,646,0,1105,1,1463,99,1001,593,1,593,1106,0,592,1006,755,664,1102,0,1,755,1106,0,647,4,754,99,109,2,1101,0,726,757,22101,0,-1,1,21102,9,1,2,21101,697,0,3,21101,0,692,0,1106,0,1913,109,-2,2106,0,0,109,2,101,0,757,706,1201,-1,0,0,1001,757,1,757,109,-2,2106,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,255,63,191,223,127,159,95,0,170,122,102,166,184,142,77,113,215,202,162,219,154,231,92,123,197,247,85,87,138,181,174,55,185,153,234,107,254,124,249,84,139,233,213,226,115,246,228,99,34,121,118,163,137,54,169,57,106,46,38,125,189,119,51,103,175,79,157,61,207,221,71,251,238,178,86,78,232,47,187,203,253,248,136,94,69,201,190,205,117,227,156,98,177,42,100,204,114,200,188,76,35,49,252,236,196,206,70,143,182,62,198,168,229,68,93,230,60,183,243,199,237,43,140,244,155,222,126,241,216,214,58,218,217,50,239,141,56,158,171,109,235,245,179,152,101,59,116,108,212,250,120,111,173,172,39,242,220,167,186,53,110,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,73,110,112,117,116,32,105,110,115,116,114,117,99,116,105,111,110,115,58,10,13,10,87,97,108,107,105,110,103,46,46,46,10,10,13,10,82,117,110,110,105,110,103,46,46,46,10,10,25,10,68,105,100,110,39,116,32,109,97,107,101,32,105,116,32,97,99,114,111,115,115,58,10,10,58,73,110,118,97,108,105,100,32,111,112,101,114,97,116,105,111,110,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,78,68,44,32,79,82,44,32,111,114,32,78,79,84,67,73,110,118,97,108,105,100,32,102,105,114,115,116,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,115,111,109,101,116,104,105,110,103,32,108,105,107,101,32,65,44,32,66,44,32,67,44,32,68,44,32,74,44,32,111,114,32,84,40,73,110,118,97,108,105,100,32,115,101,99,111,110,100,32,97,114,103,117,109,101,110,116,59,32,101,120,112,101,99,116,101,100,32,74,32,111,114,32,84,52,79,117,116,32,111,102,32,109,101,109,111,114,121,59,32,97,116,32,109,111,115,116,32,49,53,32,105,110,115,116,114,117,99,116,105,111,110,115,32,99,97,110,32,98,101,32,115,116,111,114,101,100,0,109,1,1005,1262,1270,3,1262,20102,1,1262,0,109,-1,2105,1,0,109,1,21102,1288,1,0,1106,0,1263,20102,1,1262,0,1101,0,0,1262,109,-1,2106,0,0,109,5,21101,0,1310,0,1106,0,1279,22102,1,1,-2,22208,-2,-4,-1,1205,-1,1332,21202,-3,1,1,21101,0,1332,0,1106,0,1421,109,-5,2105,1,0,109,2,21101,1346,0,0,1105,1,1263,21208,1,32,-1,1205,-1,1363,21208,1,9,-1,1205,-1,1363,1105,1,1373,21102,1370,1,0,1105,1,1279,1105,1,1339,109,-2,2105,1,0,109,5,1202,-4,1,1385,21002,0,1,-2,22101,1,-4,-4,21102,0,1,-3,22208,-3,-2,-1,1205,-1,1416,2201,-4,-3,1408,4,0,21201,-3,1,-3,1105,1,1396,109,-5,2105,1,0,109,2,104,10,21202,-1,1,1,21102,1436,1,0,1106,0,1378,104,10,99,109,-2,2105,1,0,109,3,20002,593,753,-1,22202,-1,-2,-1,201,-1,754,754,109,-3,2106,0,0,109,10,21101,0,5,-5,21102,1,1,-4,21101,0,0,-3,1206,-9,1555,21101,3,0,-6,21102,1,5,-7,22208,-7,-5,-8,1206,-8,1507,22208,-6,-4,-8,1206,-8,1507,104,64,1106,0,1529,1205,-6,1527,1201,-7,716,1515,21002,0,-11,-8,21201,-8,46,-8,204,-8,1105,1,1529,104,46,21201,-7,1,-7,21207,-7,22,-8,1205,-8,1488,104,10,21201,-6,-1,-6,21207,-6,0,-8,1206,-8,1484,104,10,21207,-4,1,-8,1206,-8,1569,21101,0,0,-9,1105,1,1689,21208,-5,21,-8,1206,-8,1583,21101,1,0,-9,1105,1,1689,1201,-5,716,1588,21001,0,0,-2,21208,-4,1,-1,22202,-2,-1,-1,1205,-2,1613,22102,1,-5,1,21101,0,1613,0,1105,1,1444,1206,-1,1634,21202,-5,1,1,21102,1,1627,0,1106,0,1694,1206,1,1634,21102,2,1,-3,22107,1,-4,-8,22201,-1,-8,-8,1206,-8,1649,21201,-5,1,-5,1206,-3,1663,21201,-3,-1,-3,21201,-4,1,-4,1105,1,1667,21201,-4,-1,-4,21208,-4,0,-1,1201,-5,716,1676,22002,0,-1,-1,1206,-1,1686,21101,0,1,-4,1105,1,1477,109,-10,2106,0,0,109,11,21101,0,0,-6,21101,0,0,-8,21102,0,1,-7,20208,-6,920,-9,1205,-9,1880,21202,-6,3,-9,1201,-9,921,1724,21002,0,1,-5,1001,1724,1,1733,20101,0,0,-4,22101,0,-4,1,21101,0,1,2,21102,1,9,3,21102,1754,1,0,1105,1,1889,1206,1,1772,2201,-10,-4,1766,1001,1766,716,1766,21001,0,0,-3,1106,0,1790,21208,-4,-1,-9,1206,-9,1786,22101,0,-8,-3,1105,1,1790,21202,-7,1,-3,1001,1733,1,1796,20102,1,0,-2,21208,-2,-1,-9,1206,-9,1812,22102,1,-8,-1,1106,0,1816,22102,1,-7,-1,21208,-5,1,-9,1205,-9,1837,21208,-5,2,-9,1205,-9,1844,21208,-3,0,-1,1106,0,1855,22202,-3,-1,-1,1106,0,1855,22201,-3,-1,-1,22107,0,-1,-1,1105,1,1855,21208,-2,-1,-9,1206,-9,1869,22102,1,-1,-8,1105,1,1873,21201,-1,0,-7,21201,-6,1,-6,1105,1,1708,22101,0,-8,-10,109,-11,2106,0,0,109,7,22207,-6,-5,-3,22207,-4,-6,-2,22201,-3,-2,-1,21208,-1,0,-6,109,-7,2106,0,0,0,109,5,1202,-2,1,1912,21207,-4,0,-1,1206,-1,1930,21101,0,0,-4,21201,-4,0,1,22102,1,-3,2,21102,1,1,3,21102,1,1949,0,1106,0,1954,109,-5,2106,0,0,109,6,21207,-4,1,-1,1206,-1,1977,22207,-5,-3,-1,1206,-1,1977,22102,1,-5,-5,1106,0,2045,21201,-5,0,1,21201,-4,-1,2,21202,-3,2,3,21102,1,1996,0,1106,0,1954,21201,1,0,-5,21101,0,1,-2,22207,-5,-3,-1,1206,-1,2015,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2037,21202,-2,1,1,21101,0,2037,0,105,1,1912,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2105,1,0 diff --git a/2019/d22/ex1/ex1.py b/2019/d22/ex1/ex1.py new file mode 100755 index 0000000..fd7fbc1 --- /dev/null +++ b/2019/d22/ex1/ex1.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python + +import dataclasses +import enum +import sys + + +class Technique(enum.Enum): + DEAL_NEW = enum.auto() + CUT = enum.auto() + DEAL_INCR = enum.auto() + + +@dataclasses.dataclass +class Instruction: + tech: Technique + n: int + + def to_linear(self) -> tuple[int, int]: + if self.tech == Technique.DEAL_NEW: + return (-1, -1) + if self.tech == Technique.CUT: + return (1, -self.n) + if self.tech == Technique.DEAL_INCR: + return (self.n, 0) + assert False # Sanity check + + def apply(self, card_pos: int, deck_size: int) -> int: + a, b = self.to_linear() + return (card_pos * a + b) % deck_size + + +def solve(input: str) -> int: + def parse_instruction(input: str) -> Instruction: + if input == "deal into new stack": + return Instruction(Technique.DEAL_NEW, 0) + n = int(input.split()[-1]) + if input.startswith("cut"): + return Instruction(Technique.CUT, n) + if input.startswith("deal with increment"): + return Instruction(Technique.DEAL_INCR, n) + assert False # Sanity check + + def parse(input: list[str]) -> list[Instruction]: + return [parse_instruction(line) for line in input] + + def find_final_pos( + card_pos: int, deck_size: int, instructions: list[Instruction] + ) -> int: + for instr in instructions: + card_pos = instr.apply(card_pos, deck_size) + return card_pos + + instructions = parse(input.splitlines()) + return find_final_pos(2019, 10007, instructions) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d22/ex1/input b/2019/d22/ex1/input new file mode 100644 index 0000000..bf68d13 --- /dev/null +++ b/2019/d22/ex1/input @@ -0,0 +1,100 @@ +deal into new stack +deal with increment 68 +cut 4888 +deal with increment 44 +cut -7998 +deal into new stack +cut -5078 +deal with increment 26 +cut 7651 +deal with increment 60 +cut 8998 +deal into new stack +deal with increment 64 +cut -8235 +deal into new stack +deal with increment 9 +cut -8586 +deal with increment 49 +cut -7466 +deal with increment 66 +cut -565 +deal with increment 19 +cut -6306 +deal with increment 67 +deal into new stack +cut 886 +deal with increment 63 +cut 3550 +deal with increment 36 +cut 5593 +deal with increment 18 +deal into new stack +deal with increment 70 +deal into new stack +cut 5168 +deal with increment 39 +cut 7701 +deal with increment 2 +deal into new stack +deal with increment 45 +cut 6021 +deal with increment 46 +cut -6927 +deal with increment 49 +cut 4054 +deal into new stack +deal with increment 33 +deal into new stack +deal with increment 11 +cut -3928 +deal with increment 19 +deal into new stack +deal with increment 32 +cut -7786 +deal with increment 27 +deal into new stack +deal with increment 37 +cut -744 +deal with increment 25 +cut -98 +deal with increment 61 +cut 2042 +deal with increment 71 +cut 5761 +deal with increment 6 +cut -2628 +deal with increment 33 +cut -9509 +deal with increment 16 +cut 2599 +deal with increment 28 +cut 2767 +deal into new stack +cut 3076 +deal with increment 61 +deal into new stack +cut 1182 +deal with increment 4 +cut 2274 +deal into new stack +deal with increment 31 +cut -5897 +deal into new stack +cut -3323 +deal with increment 29 +cut 879 +deal with increment 12 +deal into new stack +deal with increment 34 +cut -5755 +deal with increment 59 +cut 7437 +deal into new stack +cut 5095 +deal into new stack +cut 453 +deal with increment 24 +cut -3537 +deal with increment 41 +deal into new stack diff --git a/2019/d22/ex2/ex2.py b/2019/d22/ex2/ex2.py new file mode 100755 index 0000000..e8dec93 --- /dev/null +++ b/2019/d22/ex2/ex2.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +import dataclasses +import enum +import sys + + +class Technique(enum.Enum): + DEAL_NEW = enum.auto() + CUT = enum.auto() + DEAL_INCR = enum.auto() + + +@dataclasses.dataclass +class Instruction: + tech: Technique + n: int + + def to_linear(self) -> tuple[int, int]: + if self.tech == Technique.DEAL_NEW: + return (-1, -1) + if self.tech == Technique.CUT: + return (1, -self.n) + if self.tech == Technique.DEAL_INCR: + return (self.n, 0) + assert False # Sanity check + + def apply(self, card_pos: int, deck_size: int) -> int: + a, b = self.to_linear() + return (card_pos * a + b) % deck_size + + +def solve(input: str) -> int: + def parse_instruction(input: str) -> Instruction: + if input == "deal into new stack": + return Instruction(Technique.DEAL_NEW, 0) + n = int(input.split()[-1]) + if input.startswith("cut"): + return Instruction(Technique.CUT, n) + if input.startswith("deal with increment"): + return Instruction(Technique.DEAL_INCR, n) + assert False # Sanity check + + def parse(input: list[str]) -> list[Instruction]: + return [parse_instruction(line) for line in input] + + def to_linear(instructions: list[Instruction]) -> tuple[int, int]: + a, b = 1, 0 + for instr in instructions: + new_a, new_b = instr.to_linear() + a = a * new_a + b = b * new_a + new_b + return a, b + + def mod_pow(n: int, pow: int, mod: int) -> int: + if pow == 0: + return 1 + if pow == 1: + return n % mod + res = mod_pow(n, pow // 2, mod) ** 2 + if pow % 2 == 1: + res *= n + return res % mod + + def mod_inverse(n: int, mod: int) -> int: + def extended_gcd(a: int, b: int) -> tuple[int, int, int]: + if b == 0: + return a, 1, 0 + gcd, x, y = extended_gcd(b, a % b) + # we want x * a + y * b == gcd + return gcd, y, x - (a // b) * y + + gcd, _, y = extended_gcd(mod, n) + assert gcd == 1 # Sanity check + return y % mod + + def find_in_pos( + card_pos: int, deck_size: int, repetitions: int, instructions: list[Instruction] + ) -> int: + a, b = to_linear(instructions) + repeat_a = mod_pow(a, repetitions, deck_size) + repeat_b = (b * (repeat_a - 1) * mod_inverse(a - 1, deck_size)) % deck_size + + return ((card_pos - repeat_b) * mod_inverse(repeat_a, deck_size)) % deck_size + + instructions = parse(input.splitlines()) + return find_in_pos(2020, 119315717514047, 101741582076661, instructions) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d22/ex2/input b/2019/d22/ex2/input new file mode 100644 index 0000000..bf68d13 --- /dev/null +++ b/2019/d22/ex2/input @@ -0,0 +1,100 @@ +deal into new stack +deal with increment 68 +cut 4888 +deal with increment 44 +cut -7998 +deal into new stack +cut -5078 +deal with increment 26 +cut 7651 +deal with increment 60 +cut 8998 +deal into new stack +deal with increment 64 +cut -8235 +deal into new stack +deal with increment 9 +cut -8586 +deal with increment 49 +cut -7466 +deal with increment 66 +cut -565 +deal with increment 19 +cut -6306 +deal with increment 67 +deal into new stack +cut 886 +deal with increment 63 +cut 3550 +deal with increment 36 +cut 5593 +deal with increment 18 +deal into new stack +deal with increment 70 +deal into new stack +cut 5168 +deal with increment 39 +cut 7701 +deal with increment 2 +deal into new stack +deal with increment 45 +cut 6021 +deal with increment 46 +cut -6927 +deal with increment 49 +cut 4054 +deal into new stack +deal with increment 33 +deal into new stack +deal with increment 11 +cut -3928 +deal with increment 19 +deal into new stack +deal with increment 32 +cut -7786 +deal with increment 27 +deal into new stack +deal with increment 37 +cut -744 +deal with increment 25 +cut -98 +deal with increment 61 +cut 2042 +deal with increment 71 +cut 5761 +deal with increment 6 +cut -2628 +deal with increment 33 +cut -9509 +deal with increment 16 +cut 2599 +deal with increment 28 +cut 2767 +deal into new stack +cut 3076 +deal with increment 61 +deal into new stack +cut 1182 +deal with increment 4 +cut 2274 +deal into new stack +deal with increment 31 +cut -5897 +deal into new stack +cut -3323 +deal with increment 29 +cut 879 +deal with increment 12 +deal into new stack +deal with increment 34 +cut -5755 +deal with increment 59 +cut 7437 +deal into new stack +cut 5095 +deal into new stack +cut 453 +deal with increment 24 +cut -3537 +deal with increment 41 +deal into new stack diff --git a/2019/d23/ex1/ex1.py b/2019/d23/ex1/ex1.py new file mode 100755 index 0000000..631dd1d --- /dev/null +++ b/2019/d23/ex1/ex1.py @@ -0,0 +1,230 @@ +#!/usr/bin/env python + +import copy +import sys +from dataclasses import dataclass, field +from enum import IntEnum +from typing import List, NamedTuple + + +class ParameterMode(IntEnum): + POSITION = 0 # Acts on address + IMMEDIATE = 1 # Acts on the immediate value + RELATIVE = 2 # Acts on offset to relative base + + +class Instruction(NamedTuple): + address: int # The address of the instruction, for convenience + op: int # The opcode + p1_mode: ParameterMode # Which mode is the first parameter in + p2_mode: ParameterMode # Which mode is the second parameter in + p3_mode: ParameterMode # Which mode is the third parameter in + + +def lookup_ops(index: int, memory: List[int]) -> Instruction: + digits = list(map(int, str(memory[index]))) + a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values + return Instruction( + address=index, + op=d * 10 + e, + p1_mode=ParameterMode(c), + p2_mode=ParameterMode(b), + p3_mode=ParameterMode(a), + ) + + +class InputInterrupt(Exception): + pass + + +class OutputInterrupt(Exception): + pass + + +@dataclass +class Computer: + memory: List[int] # Memory space + rip: int = 0 # Instruction pointer + input_list: List[int] = field(default_factory=list) + output_list: List[int] = field(default_factory=list) + is_halted: bool = field(default=False, init=False) + relative_base: int = field(default=0, init=False) + + def run(self) -> None: + while not self.is_halted: + self.run_single() + + def run_no_output_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_single() + except OutputInterrupt: + continue + + def run_single(self) -> None: # Returns True when halted + instr = lookup_ops(self.rip, self.memory) + if instr.op == 99: # Halt + self.is_halted = True + elif instr.op == 1: # Sum + self._do_addition(instr) + elif instr.op == 2: # Multiplication + self._do_multiplication(instr) + elif instr.op == 3: # Load from input + self._do_input(instr) + elif instr.op == 4: # Store to output + self._do_output(instr) + elif instr.op == 5: # Jump if true + self._do_jump_if_true(instr) + elif instr.op == 6: # Jump if false + self._do_jump_if_false(instr) + elif instr.op == 7: # Less than + self._do_less_than(instr) + elif instr.op == 8: # Equal to + self._do_equal_to(instr) + elif instr.op == 9: # Change relative base + self._do_change_relative_base(instr) + else: + assert False # Sanity check + + def _fill_to_addres(self, address: int) -> None: + values = address - len(self.memory) + 1 + if values <= 0: + return + for __ in range(values): + self.memory.append(0) + + def _get_value(self, mode: ParameterMode, val: int) -> int: + if mode == ParameterMode.POSITION: + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + elif mode == ParameterMode.RELATIVE: + val += self.relative_base + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + assert mode == ParameterMode.IMMEDIATE # Sanity check + return val + + def _set_value(self, mode: ParameterMode, address: int, value: int) -> None: + if mode == ParameterMode.RELATIVE: + address += self.relative_base + else: + assert mode == ParameterMode.POSITION # Sanity check + + assert address >= 0 # Sanity check + self._fill_to_addres(address) + + self.memory[address] = value + + def _do_addition(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs + rhs) + + self.rip += 4 # Length of the instruction + + def _do_multiplication(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs * rhs) + + self.rip += 4 # Length of the instruction + + def _do_input(self, instr: Instruction) -> None: + if len(self.input_list) == 0: + raise InputInterrupt # No input, halt until an input is provided + + value = int(self.input_list.pop(0)) + param = self.memory[instr.address + 1] + + self._set_value(instr.p1_mode, param, value) + + self.rip += 2 # Length of the instruction + + def _do_output(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.output_list.append(value) + + self.rip += 2 # Length of the instruction + raise OutputInterrupt # Alert that we got an output to give + + def _do_jump_if_true(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond != 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_jump_if_false(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond == 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_less_than(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_equal_to(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_change_relative_base(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.relative_base += value + self.rip += 2 # Length of the instruction + + +def solve(input: str) -> int: + memory = [int(n) for n in input.split(",")] + network = [Computer(copy.deepcopy(memory)) for _ in range(50)] + + for i, computer in enumerate(network): + computer.input_list.append(i) + + while True: + for i, computer in enumerate(network): + try: + computer.run_single() + except InputInterrupt: + computer.input_list.append(-1) + # Re-run it to actually execute the instruction + computer.run_single() + except OutputInterrupt: + if len(computer.output_list) == 3: + addr, x, y = computer.output_list + computer.output_list.clear() + if addr == 255: + return y + network[addr].input_list += [x, y] + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d23/ex1/input b/2019/d23/ex1/input new file mode 100644 index 0000000..3a9c92f --- /dev/null +++ b/2019/d23/ex1/input @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2231,105,1,0,1614,1241,1082,2035,711,1020,2128,1750,1841,678,1719,1655,2198,1876,1119,2099,944,1280,771,837,1482,1515,1451,1581,2068,913,1779,608,643,1550,1909,1414,1183,983,1348,1315,866,740,1942,1810,2006,1212,1379,2157,1686,1977,571,804,1051,1148,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1105,1,73,3,65,20101,0,64,1,20101,0,66,2,21102,105,1,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,132,1,132,68,132,1001,0,0,62,1001,132,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,0,1,0,1001,161,1,169,102,1,65,0,1101,1,0,61,1101,0,0,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1106,0,178,21102,1,210,0,105,1,69,1202,1,1,70,1101,0,0,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1105,1,73,109,4,21102,1,0,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1105,1,263,22101,0,-3,-3,109,-4,2106,0,0,109,4,21101,1,0,-3,21102,1,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,22102,1,-3,-3,109,-4,2106,0,0,109,1,101,1,68,358,21002,0,1,1,101,3,68,366,21001,0,0,2,21102,1,376,0,1106,0,436,21202,1,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21101,0,0,-4,21102,1,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,470,21001,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1105,1,547,21102,1,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1105,1,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2105,1,0,1102,37061,1,66,1102,4,1,67,1101,0,598,68,1101,0,302,69,1102,1,1,71,1102,606,1,72,1106,0,73,0,0,0,0,0,0,0,0,42,79162,1102,10177,1,66,1102,3,1,67,1102,635,1,68,1101,302,0,69,1102,1,1,71,1102,1,641,72,1105,1,73,0,0,0,0,0,0,42,118743,1102,86291,1,66,1101,1,0,67,1101,0,670,68,1101,0,556,69,1101,0,3,71,1102,1,672,72,1106,0,73,1,5,31,189578,31,284367,43,3574,1101,2999,0,66,1101,1,0,67,1102,1,705,68,1101,0,556,69,1101,2,0,71,1101,707,0,72,1105,1,73,1,4021,38,305871,21,5059,1101,0,28661,66,1102,1,1,67,1101,0,738,68,1102,1,556,69,1101,0,0,71,1102,740,1,72,1105,1,73,1,1004,1101,0,3769,66,1101,0,1,67,1101,767,0,68,1102,556,1,69,1102,1,1,71,1101,769,0,72,1105,1,73,1,18,46,74122,1101,0,9857,66,1102,1,1,67,1101,798,0,68,1102,556,1,69,1101,0,2,71,1101,800,0,72,1106,0,73,1,10,31,94789,43,1787,1101,0,32969,66,1102,1,1,67,1102,1,831,68,1102,556,1,69,1102,2,1,71,1101,0,833,72,1105,1,73,1,3,27,10177,27,20354,1102,1,88799,66,1102,1,1,67,1102,1,864,68,1102,556,1,69,1101,0,0,71,1101,0,866,72,1106,0,73,1,1699,1101,0,9293,66,1101,1,0,67,1102,1,893,68,1102,556,1,69,1101,9,0,71,1102,895,1,72,1105,1,73,1,1,46,37061,30,34457,16,17734,12,91502,20,68777,13,170162,8,269013,33,276604,21,10118,1101,0,14657,66,1101,1,0,67,1102,1,940,68,1101,0,556,69,1102,1,1,71,1102,942,1,72,1106,0,73,1,33521,30,68914,1101,0,8867,66,1102,5,1,67,1101,971,0,68,1101,302,0,69,1102,1,1,71,1101,0,981,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,42,39581,1102,1,69151,66,1102,4,1,67,1101,0,1010,68,1101,302,0,69,1102,1,1,71,1101,1018,0,72,1106,0,73,0,0,0,0,0,0,0,0,3,92362,1101,0,33493,66,1102,1,1,67,1101,1047,0,68,1102,1,556,69,1101,1,0,71,1101,1049,0,72,1106,0,73,1,997,16,8867,1101,0,69959,66,1102,1,1,67,1101,1078,0,68,1101,0,556,69,1102,1,1,71,1101,1080,0,72,1106,0,73,1,223,33,138302,1102,21893,1,66,1101,4,0,67,1101,1109,0,68,1101,253,0,69,1102,1,1,71,1102,1117,1,72,1106,0,73,0,0,0,0,0,0,0,0,44,66089,1102,27751,1,66,1102,1,1,67,1101,1146,0,68,1101,556,0,69,1102,0,1,71,1102,1148,1,72,1105,1,73,1,1295,1102,1,53381,66,1101,0,3,67,1101,1175,0,68,1101,0,302,69,1101,0,1,71,1101,0,1181,72,1106,0,73,0,0,0,0,0,0,2,65679,1102,23677,1,66,1101,1,0,67,1101,1210,0,68,1101,556,0,69,1102,1,0,71,1101,0,1212,72,1105,1,73,1,1080,1101,0,3257,66,1101,1,0,67,1102,1239,1,68,1101,556,0,69,1101,0,0,71,1101,0,1241,72,1106,0,73,1,1993,1102,1,99961,66,1102,1,1,67,1101,0,1268,68,1102,1,556,69,1102,1,5,71,1101,1270,0,72,1106,0,73,1,2,16,44335,38,101957,8,179342,43,5361,43,7148,1101,10883,0,66,1101,0,3,67,1101,0,1307,68,1101,302,0,69,1101,0,1,71,1102,1313,1,72,1106,0,73,0,0,0,0,0,0,2,21893,1101,10859,0,66,1101,2,0,67,1101,0,1342,68,1101,0,302,69,1101,0,1,71,1102,1,1346,72,1106,0,73,0,0,0,0,38,203914,1101,0,90163,66,1102,1,1,67,1102,1375,1,68,1102,1,556,69,1101,0,1,71,1101,0,1377,72,1106,0,73,1,37,46,111183,1101,0,39581,66,1101,3,0,67,1101,1406,0,68,1101,253,0,69,1101,0,1,71,1101,0,1412,72,1106,0,73,0,0,0,0,0,0,35,21718,1101,0,94789,66,1101,0,4,67,1102,1,1441,68,1102,302,1,69,1101,1,0,71,1101,0,1449,72,1105,1,73,0,0,0,0,0,0,0,0,43,8935,1101,1571,0,66,1101,1,0,67,1102,1,1478,68,1102,1,556,69,1102,1,1,71,1102,1,1480,72,1105,1,73,1,-12,21,15177,1101,0,68777,66,1102,1,2,67,1101,1509,0,68,1102,1,302,69,1102,1,1,71,1102,1513,1,72,1105,1,73,0,0,0,0,13,85081,1102,1,5059,66,1102,1,3,67,1101,1542,0,68,1102,302,1,69,1101,0,1,71,1101,0,1548,72,1105,1,73,0,0,0,0,0,0,17,10883,1101,0,2099,66,1102,1,1,67,1101,1577,0,68,1102,1,556,69,1101,1,0,71,1102,1579,1,72,1105,1,73,1,546,46,148244,1102,1,1187,66,1101,1,0,67,1101,0,1608,68,1101,0,556,69,1102,1,2,71,1102,1,1610,72,1106,0,73,1,31,16,26601,16,35468,1102,1,30757,66,1101,1,0,67,1101,0,1641,68,1102,556,1,69,1101,0,6,71,1101,0,1643,72,1105,1,73,1,24015,3,46181,17,21766,17,32649,49,53381,49,106762,49,160143,1101,41759,0,66,1101,0,1,67,1102,1682,1,68,1101,556,0,69,1101,0,1,71,1102,1684,1,72,1105,1,73,1,160,43,10722,1101,0,66089,66,1101,2,0,67,1102,1713,1,68,1101,0,351,69,1102,1,1,71,1102,1717,1,72,1106,0,73,0,0,0,0,255,30757,1102,1093,1,66,1101,1,0,67,1101,1746,0,68,1101,0,556,69,1102,1,1,71,1101,0,1748,72,1105,1,73,1,32,35,10859,1101,85091,0,66,1102,1,1,67,1102,1777,1,68,1101,0,556,69,1102,0,1,71,1102,1,1779,72,1106,0,73,1,1773,1102,1,70177,66,1102,1,1,67,1102,1806,1,68,1101,556,0,69,1101,1,0,71,1101,0,1808,72,1106,0,73,1,125,31,379156,1102,1,9281,66,1101,0,1,67,1101,1837,0,68,1102,556,1,69,1102,1,1,71,1102,1,1839,72,1105,1,73,1,17987,12,45751,1102,89671,1,66,1101,0,3,67,1101,1868,0,68,1101,302,0,69,1101,1,0,71,1101,0,1874,72,1106,0,73,0,0,0,0,0,0,33,69151,1102,85081,1,66,1102,1,2,67,1102,1903,1,68,1102,302,1,69,1101,1,0,71,1101,1907,0,72,1106,0,73,0,0,0,0,8,89671,1102,1,34457,66,1102,1,2,67,1101,0,1936,68,1102,302,1,69,1102,1,1,71,1101,0,1940,72,1106,0,73,0,0,0,0,27,30531,1102,1,101957,66,1101,3,0,67,1102,1,1969,68,1101,0,302,69,1102,1,1,71,1102,1975,1,72,1105,1,73,0,0,0,0,0,0,2,43786,1102,1,39191,66,1102,1,1,67,1102,1,2004,68,1101,556,0,69,1101,0,0,71,1102,1,2006,72,1106,0,73,1,1654,1101,48197,0,66,1101,1,0,67,1102,1,2033,68,1102,1,556,69,1102,1,0,71,1102,2035,1,72,1105,1,73,1,1410,1101,46181,0,66,1102,2,1,67,1102,2062,1,68,1102,1,302,69,1102,1,1,71,1101,0,2066,72,1105,1,73,0,0,0,0,2,87572,1102,1,36671,66,1102,1,1,67,1102,2095,1,68,1102,556,1,69,1102,1,1,71,1101,0,2097,72,1105,1,73,1,184,33,207453,1101,29863,0,66,1102,1,1,67,1102,1,2126,68,1101,556,0,69,1102,1,0,71,1102,1,2128,72,1105,1,73,1,1733,1102,30577,1,66,1101,1,0,67,1101,0,2155,68,1102,1,556,69,1101,0,0,71,1101,0,2157,72,1105,1,73,1,1195,1102,1,1787,66,1102,6,1,67,1101,2184,0,68,1102,1,302,69,1102,1,1,71,1102,2196,1,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,44,132178,1101,45751,0,66,1101,0,2,67,1102,1,2225,68,1101,0,302,69,1101,0,1,71,1102,2229,1,72,1105,1,73,0,0,0,0,20,137554 diff --git a/2019/d23/ex2/ex2.py b/2019/d23/ex2/ex2.py new file mode 100755 index 0000000..9fd0423 --- /dev/null +++ b/2019/d23/ex2/ex2.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python + +import copy +import sys +from dataclasses import dataclass, field +from enum import IntEnum +from typing import List, NamedTuple + + +class ParameterMode(IntEnum): + POSITION = 0 # Acts on address + IMMEDIATE = 1 # Acts on the immediate value + RELATIVE = 2 # Acts on offset to relative base + + +class Instruction(NamedTuple): + address: int # The address of the instruction, for convenience + op: int # The opcode + p1_mode: ParameterMode # Which mode is the first parameter in + p2_mode: ParameterMode # Which mode is the second parameter in + p3_mode: ParameterMode # Which mode is the third parameter in + + +def lookup_ops(index: int, memory: List[int]) -> Instruction: + digits = list(map(int, str(memory[index]))) + a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values + return Instruction( + address=index, + op=d * 10 + e, + p1_mode=ParameterMode(c), + p2_mode=ParameterMode(b), + p3_mode=ParameterMode(a), + ) + + +class InputInterrupt(Exception): + pass + + +class OutputInterrupt(Exception): + pass + + +@dataclass +class Computer: + memory: List[int] # Memory space + rip: int = 0 # Instruction pointer + input_list: List[int] = field(default_factory=list) + output_list: List[int] = field(default_factory=list) + is_halted: bool = field(default=False, init=False) + relative_base: int = field(default=0, init=False) + + def run(self) -> None: + while not self.is_halted: + self.run_single() + + def run_no_output_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_single() + except OutputInterrupt: + continue + + def run_single(self) -> None: # Returns True when halted + instr = lookup_ops(self.rip, self.memory) + if instr.op == 99: # Halt + self.is_halted = True + elif instr.op == 1: # Sum + self._do_addition(instr) + elif instr.op == 2: # Multiplication + self._do_multiplication(instr) + elif instr.op == 3: # Load from input + self._do_input(instr) + elif instr.op == 4: # Store to output + self._do_output(instr) + elif instr.op == 5: # Jump if true + self._do_jump_if_true(instr) + elif instr.op == 6: # Jump if false + self._do_jump_if_false(instr) + elif instr.op == 7: # Less than + self._do_less_than(instr) + elif instr.op == 8: # Equal to + self._do_equal_to(instr) + elif instr.op == 9: # Change relative base + self._do_change_relative_base(instr) + else: + assert False # Sanity check + + def _fill_to_addres(self, address: int) -> None: + values = address - len(self.memory) + 1 + if values <= 0: + return + for __ in range(values): + self.memory.append(0) + + def _get_value(self, mode: ParameterMode, val: int) -> int: + if mode == ParameterMode.POSITION: + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + elif mode == ParameterMode.RELATIVE: + val += self.relative_base + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + assert mode == ParameterMode.IMMEDIATE # Sanity check + return val + + def _set_value(self, mode: ParameterMode, address: int, value: int) -> None: + if mode == ParameterMode.RELATIVE: + address += self.relative_base + else: + assert mode == ParameterMode.POSITION # Sanity check + + assert address >= 0 # Sanity check + self._fill_to_addres(address) + + self.memory[address] = value + + def _do_addition(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs + rhs) + + self.rip += 4 # Length of the instruction + + def _do_multiplication(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs * rhs) + + self.rip += 4 # Length of the instruction + + def _do_input(self, instr: Instruction) -> None: + if len(self.input_list) == 0: + raise InputInterrupt # No input, halt until an input is provided + + value = int(self.input_list.pop(0)) + param = self.memory[instr.address + 1] + + self._set_value(instr.p1_mode, param, value) + + self.rip += 2 # Length of the instruction + + def _do_output(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.output_list.append(value) + + self.rip += 2 # Length of the instruction + raise OutputInterrupt # Alert that we got an output to give + + def _do_jump_if_true(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond != 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_jump_if_false(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond == 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_less_than(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_equal_to(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_change_relative_base(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.relative_base += value + self.rip += 2 # Length of the instruction + + +def solve(input: str) -> int: + memory = [int(n) for n in input.split(",")] + network = [Computer(copy.deepcopy(memory)) for _ in range(50)] + nat: tuple[int, int] = -1, -1 # Init to a random value + previous_nat: tuple[int, int] = nat # Same + + for i, computer in enumerate(network): + computer.input_list.append(i) + + is_idle: set[int] = set() + idle_count = 0 + while True: + for i, computer in enumerate(network): + try: + computer.run_single() + except InputInterrupt: + computer.input_list.append(-1) + # Re-run it to actually execute the instruction + computer.run_single() + is_idle.add(i) + except OutputInterrupt: + is_idle.discard(i) + if len(computer.output_list) == 3: + addr, x, y = computer.output_list + computer.output_list.clear() + if addr == 255: + nat = x, y + continue + is_idle.discard(addr) + network[addr].input_list += [x, y] + if len(is_idle) == len(network): + idle_count += 1 + else: + idle_count = 0 + # Use NAT after a short amount of time being idle + if idle_count == 100: + is_idle.clear() + idle_count = 0 + if previous_nat[1] == nat[1]: + return nat[1] + network[0].input_list += nat + previous_nat = nat + + assert False # Sanity check + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d23/ex2/input b/2019/d23/ex2/input new file mode 100644 index 0000000..3a9c92f --- /dev/null +++ b/2019/d23/ex2/input @@ -0,0 +1 @@ +3,62,1001,62,11,10,109,2231,105,1,0,1614,1241,1082,2035,711,1020,2128,1750,1841,678,1719,1655,2198,1876,1119,2099,944,1280,771,837,1482,1515,1451,1581,2068,913,1779,608,643,1550,1909,1414,1183,983,1348,1315,866,740,1942,1810,2006,1212,1379,2157,1686,1977,571,804,1051,1148,0,0,0,0,0,0,0,0,0,0,0,0,3,64,1008,64,-1,62,1006,62,88,1006,61,170,1105,1,73,3,65,20101,0,64,1,20101,0,66,2,21102,105,1,0,1105,1,436,1201,1,-1,64,1007,64,0,62,1005,62,73,7,64,67,62,1006,62,73,1002,64,2,132,1,132,68,132,1001,0,0,62,1001,132,1,140,8,0,65,63,2,63,62,62,1005,62,73,1002,64,2,161,1,161,68,161,1101,0,1,0,1001,161,1,169,102,1,65,0,1101,1,0,61,1101,0,0,63,7,63,67,62,1006,62,203,1002,63,2,194,1,68,194,194,1006,0,73,1001,63,1,63,1106,0,178,21102,1,210,0,105,1,69,1202,1,1,70,1101,0,0,63,7,63,71,62,1006,62,250,1002,63,2,234,1,72,234,234,4,0,101,1,234,240,4,0,4,70,1001,63,1,63,1105,1,218,1105,1,73,109,4,21102,1,0,-3,21102,0,1,-2,20207,-2,67,-1,1206,-1,293,1202,-2,2,283,101,1,283,283,1,68,283,283,22001,0,-3,-3,21201,-2,1,-2,1105,1,263,22101,0,-3,-3,109,-4,2106,0,0,109,4,21101,1,0,-3,21102,1,0,-2,20207,-2,67,-1,1206,-1,342,1202,-2,2,332,101,1,332,332,1,68,332,332,22002,0,-3,-3,21201,-2,1,-2,1106,0,312,22102,1,-3,-3,109,-4,2106,0,0,109,1,101,1,68,358,21002,0,1,1,101,3,68,366,21001,0,0,2,21102,1,376,0,1106,0,436,21202,1,1,0,109,-1,2106,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21202,-6,10,-5,22207,-7,-5,-5,1205,-5,521,21101,0,0,-4,21102,1,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,385,470,21001,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,496,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,515,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,461,1105,1,547,21102,1,-1,-4,21202,-6,-1,-6,21207,-7,0,-5,1205,-5,547,22201,-7,-6,-7,21201,-4,1,-4,1105,1,529,21201,-4,0,-7,109,-8,2106,0,0,109,1,101,1,68,564,20102,1,0,0,109,-1,2105,1,0,1102,37061,1,66,1102,4,1,67,1101,0,598,68,1101,0,302,69,1102,1,1,71,1102,606,1,72,1106,0,73,0,0,0,0,0,0,0,0,42,79162,1102,10177,1,66,1102,3,1,67,1102,635,1,68,1101,302,0,69,1102,1,1,71,1102,1,641,72,1105,1,73,0,0,0,0,0,0,42,118743,1102,86291,1,66,1101,1,0,67,1101,0,670,68,1101,0,556,69,1101,0,3,71,1102,1,672,72,1106,0,73,1,5,31,189578,31,284367,43,3574,1101,2999,0,66,1101,1,0,67,1102,1,705,68,1101,0,556,69,1101,2,0,71,1101,707,0,72,1105,1,73,1,4021,38,305871,21,5059,1101,0,28661,66,1102,1,1,67,1101,0,738,68,1102,1,556,69,1101,0,0,71,1102,740,1,72,1105,1,73,1,1004,1101,0,3769,66,1101,0,1,67,1101,767,0,68,1102,556,1,69,1102,1,1,71,1101,769,0,72,1105,1,73,1,18,46,74122,1101,0,9857,66,1102,1,1,67,1101,798,0,68,1102,556,1,69,1101,0,2,71,1101,800,0,72,1106,0,73,1,10,31,94789,43,1787,1101,0,32969,66,1102,1,1,67,1102,1,831,68,1102,556,1,69,1102,2,1,71,1101,0,833,72,1105,1,73,1,3,27,10177,27,20354,1102,1,88799,66,1102,1,1,67,1102,1,864,68,1102,556,1,69,1101,0,0,71,1101,0,866,72,1106,0,73,1,1699,1101,0,9293,66,1101,1,0,67,1102,1,893,68,1102,556,1,69,1101,9,0,71,1102,895,1,72,1105,1,73,1,1,46,37061,30,34457,16,17734,12,91502,20,68777,13,170162,8,269013,33,276604,21,10118,1101,0,14657,66,1101,1,0,67,1102,1,940,68,1101,0,556,69,1102,1,1,71,1102,942,1,72,1106,0,73,1,33521,30,68914,1101,0,8867,66,1102,5,1,67,1101,971,0,68,1101,302,0,69,1102,1,1,71,1101,0,981,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,42,39581,1102,1,69151,66,1102,4,1,67,1101,0,1010,68,1101,302,0,69,1102,1,1,71,1101,1018,0,72,1106,0,73,0,0,0,0,0,0,0,0,3,92362,1101,0,33493,66,1102,1,1,67,1101,1047,0,68,1102,1,556,69,1101,1,0,71,1101,1049,0,72,1106,0,73,1,997,16,8867,1101,0,69959,66,1102,1,1,67,1101,1078,0,68,1101,0,556,69,1102,1,1,71,1101,1080,0,72,1106,0,73,1,223,33,138302,1102,21893,1,66,1101,4,0,67,1101,1109,0,68,1101,253,0,69,1102,1,1,71,1102,1117,1,72,1106,0,73,0,0,0,0,0,0,0,0,44,66089,1102,27751,1,66,1102,1,1,67,1101,1146,0,68,1101,556,0,69,1102,0,1,71,1102,1148,1,72,1105,1,73,1,1295,1102,1,53381,66,1101,0,3,67,1101,1175,0,68,1101,0,302,69,1101,0,1,71,1101,0,1181,72,1106,0,73,0,0,0,0,0,0,2,65679,1102,23677,1,66,1101,1,0,67,1101,1210,0,68,1101,556,0,69,1102,1,0,71,1101,0,1212,72,1105,1,73,1,1080,1101,0,3257,66,1101,1,0,67,1102,1239,1,68,1101,556,0,69,1101,0,0,71,1101,0,1241,72,1106,0,73,1,1993,1102,1,99961,66,1102,1,1,67,1101,0,1268,68,1102,1,556,69,1102,1,5,71,1101,1270,0,72,1106,0,73,1,2,16,44335,38,101957,8,179342,43,5361,43,7148,1101,10883,0,66,1101,0,3,67,1101,0,1307,68,1101,302,0,69,1101,0,1,71,1102,1313,1,72,1106,0,73,0,0,0,0,0,0,2,21893,1101,10859,0,66,1101,2,0,67,1101,0,1342,68,1101,0,302,69,1101,0,1,71,1102,1,1346,72,1106,0,73,0,0,0,0,38,203914,1101,0,90163,66,1102,1,1,67,1102,1375,1,68,1102,1,556,69,1101,0,1,71,1101,0,1377,72,1106,0,73,1,37,46,111183,1101,0,39581,66,1101,3,0,67,1101,1406,0,68,1101,253,0,69,1101,0,1,71,1101,0,1412,72,1106,0,73,0,0,0,0,0,0,35,21718,1101,0,94789,66,1101,0,4,67,1102,1,1441,68,1102,302,1,69,1101,1,0,71,1101,0,1449,72,1105,1,73,0,0,0,0,0,0,0,0,43,8935,1101,1571,0,66,1101,1,0,67,1102,1,1478,68,1102,1,556,69,1102,1,1,71,1102,1,1480,72,1105,1,73,1,-12,21,15177,1101,0,68777,66,1102,1,2,67,1101,1509,0,68,1102,1,302,69,1102,1,1,71,1102,1513,1,72,1105,1,73,0,0,0,0,13,85081,1102,1,5059,66,1102,1,3,67,1101,1542,0,68,1102,302,1,69,1101,0,1,71,1101,0,1548,72,1105,1,73,0,0,0,0,0,0,17,10883,1101,0,2099,66,1102,1,1,67,1101,1577,0,68,1102,1,556,69,1101,1,0,71,1102,1579,1,72,1105,1,73,1,546,46,148244,1102,1,1187,66,1101,1,0,67,1101,0,1608,68,1101,0,556,69,1102,1,2,71,1102,1,1610,72,1106,0,73,1,31,16,26601,16,35468,1102,1,30757,66,1101,1,0,67,1101,0,1641,68,1102,556,1,69,1101,0,6,71,1101,0,1643,72,1105,1,73,1,24015,3,46181,17,21766,17,32649,49,53381,49,106762,49,160143,1101,41759,0,66,1101,0,1,67,1102,1682,1,68,1101,556,0,69,1101,0,1,71,1102,1684,1,72,1105,1,73,1,160,43,10722,1101,0,66089,66,1101,2,0,67,1102,1713,1,68,1101,0,351,69,1102,1,1,71,1102,1717,1,72,1106,0,73,0,0,0,0,255,30757,1102,1093,1,66,1101,1,0,67,1101,1746,0,68,1101,0,556,69,1102,1,1,71,1101,0,1748,72,1105,1,73,1,32,35,10859,1101,85091,0,66,1102,1,1,67,1102,1777,1,68,1101,0,556,69,1102,0,1,71,1102,1,1779,72,1106,0,73,1,1773,1102,1,70177,66,1102,1,1,67,1102,1806,1,68,1101,556,0,69,1101,1,0,71,1101,0,1808,72,1106,0,73,1,125,31,379156,1102,1,9281,66,1101,0,1,67,1101,1837,0,68,1102,556,1,69,1102,1,1,71,1102,1,1839,72,1105,1,73,1,17987,12,45751,1102,89671,1,66,1101,0,3,67,1101,1868,0,68,1101,302,0,69,1101,1,0,71,1101,0,1874,72,1106,0,73,0,0,0,0,0,0,33,69151,1102,85081,1,66,1102,1,2,67,1102,1903,1,68,1102,302,1,69,1101,1,0,71,1101,1907,0,72,1106,0,73,0,0,0,0,8,89671,1102,1,34457,66,1102,1,2,67,1101,0,1936,68,1102,302,1,69,1102,1,1,71,1101,0,1940,72,1106,0,73,0,0,0,0,27,30531,1102,1,101957,66,1101,3,0,67,1102,1,1969,68,1101,0,302,69,1102,1,1,71,1102,1975,1,72,1105,1,73,0,0,0,0,0,0,2,43786,1102,1,39191,66,1102,1,1,67,1102,1,2004,68,1101,556,0,69,1101,0,0,71,1102,1,2006,72,1106,0,73,1,1654,1101,48197,0,66,1101,1,0,67,1102,1,2033,68,1102,1,556,69,1102,1,0,71,1102,2035,1,72,1105,1,73,1,1410,1101,46181,0,66,1102,2,1,67,1102,2062,1,68,1102,1,302,69,1102,1,1,71,1101,0,2066,72,1105,1,73,0,0,0,0,2,87572,1102,1,36671,66,1102,1,1,67,1102,2095,1,68,1102,556,1,69,1102,1,1,71,1101,0,2097,72,1105,1,73,1,184,33,207453,1101,29863,0,66,1102,1,1,67,1102,1,2126,68,1101,556,0,69,1102,1,0,71,1102,1,2128,72,1105,1,73,1,1733,1102,30577,1,66,1101,1,0,67,1101,0,2155,68,1102,1,556,69,1101,0,0,71,1101,0,2157,72,1105,1,73,1,1195,1102,1,1787,66,1102,6,1,67,1101,2184,0,68,1102,1,302,69,1102,1,1,71,1102,2196,1,72,1106,0,73,0,0,0,0,0,0,0,0,0,0,0,0,44,132178,1101,45751,0,66,1101,0,2,67,1102,1,2225,68,1101,0,302,69,1101,0,1,71,1102,2229,1,72,1105,1,73,0,0,0,0,20,137554 diff --git a/2019/d24/ex1/ex1.py b/2019/d24/ex1/ex1.py new file mode 100755 index 0000000..33b0ada --- /dev/null +++ b/2019/d24/ex1/ex1.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +import itertools +import sys +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +DIMS = 5 + + +def solve(input: str) -> int: + def parse(input: list[str]) -> frozenset[Point]: + return frozenset( + Point(x, y) + for x, line in enumerate(input) + for y, c in enumerate(line) + if c == "#" + ) + + def step(bugs: frozenset[Point]) -> frozenset[Point]: + res: set[Point] = set() + for p in map(Point._make, itertools.product(range(DIMS), range(DIMS))): + neighbours = len(set(p.neighbours()) & bugs) + # Bug dies if not exactly one neighbour + if p in bugs and neighbours != 1: + continue + # An empty space stays empty if it doesn't have 1 or 2 neighbours + if p not in bugs and neighbours not in (1, 2): + continue + res.add(p) + return frozenset(res) + + def biodiversity(bugs: frozenset[Point]) -> int: + res = 0 + for x, y in itertools.product(range(DIMS), range(DIMS)): + res |= (Point(x, y) in bugs) << (x * DIMS + y) + return res + + bugs = parse(input.splitlines()) + layouts: set[frozenset[Point]] = set() + + while True: + layouts.add(frozenset(bugs)) + bugs = step(bugs) + if bugs in layouts: + return biodiversity(bugs) + + assert False # Sanity check + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d24/ex1/input b/2019/d24/ex1/input new file mode 100644 index 0000000..32e8431 --- /dev/null +++ b/2019/d24/ex1/input @@ -0,0 +1,5 @@ +..#.# +.#.## +...#. +...## +#.### diff --git a/2019/d24/ex2/ex2.py b/2019/d24/ex2/ex2.py new file mode 100755 index 0000000..d2fbcc6 --- /dev/null +++ b/2019/d24/ex2/ex2.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python + +import itertools +import sys +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + def neighbours(self) -> Iterator["Point"]: + for dx, dy in ( + (-1, 0), + (1, 0), + (0, -1), + (0, 1), + ): + yield Point(self.x + dx, self.y + dy) + + +DIMS = 5 + +INNER_NEIGHBOURS = { + Point(1, 2): {Point(0, y) for y in range(DIMS)}, + Point(3, 2): {Point(DIMS - 1, y) for y in range(DIMS)}, + Point(2, 1): {Point(x, 0) for x in range(DIMS)}, + Point(2, 3): {Point(x, DIMS - 1) for x in range(DIMS)}, +} + +X_OUTER_NEIGHBOUR = { + p: n for n in (Point(1, 2), Point(3, 2)) for p in INNER_NEIGHBOURS[n] +} +Y_OUTER_NEIGHBOUR = { + p: n for n in (Point(2, 1), Point(2, 3)) for p in INNER_NEIGHBOURS[n] +} + + +def solve(input: str) -> int: + def parse(input: list[str]) -> set[tuple[Point, int]]: + return { + (Point(x, y), 0) + for x, line in enumerate(input) + for y, c in enumerate(line) + if c == "#" + } + + def grid_neighbours(p: Point, level: int) -> set[tuple[Point, int]]: + assert p != Point(2, 2) # Sanity check + + res: set[tuple[Point, int]] = set() + for n in p.neighbours(): + if n == Point(2, 2): + res |= {(n, level + 1) for n in INNER_NEIGHBOURS[p]} + elif n.x in (-1, DIMS): + res.add((X_OUTER_NEIGHBOUR[p], level - 1)) + elif n.y in (-1, DIMS): + res.add((Y_OUTER_NEIGHBOUR[p], level - 1)) + else: + res.add((n, level)) + + return res + + def step(bugs: set[tuple[Point, int]]) -> set[tuple[Point, int]]: + res: set[tuple[Point, int]] = set() + min_level, max_level = ( + min(level for _, level in bugs), + max(level for _, level in bugs), + ) + for level in range(min_level - 1, max_level + 1 + 1): + for p in map(Point._make, itertools.product(range(DIMS), range(DIMS))): + if p == Point(2, 2): + continue + neighbours = len(grid_neighbours(p, level) & bugs) + # Bug dies if not exactly one neighbour + if (p, level) in bugs and neighbours != 1: + continue + # An empty space stays empty if it doesn't have 1 or 2 neighbours + if (p, level) not in bugs and neighbours not in (1, 2): + continue + res.add((p, level)) + return res + + bugs = parse(input.splitlines()) + for _ in range(200): + bugs = step(bugs) + return len(bugs) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d24/ex2/input b/2019/d24/ex2/input new file mode 100644 index 0000000..32e8431 --- /dev/null +++ b/2019/d24/ex2/input @@ -0,0 +1,5 @@ +..#.# +.#.## +...#. +...## +#.### diff --git a/2019/d25/ex1/ex1.py b/2019/d25/ex1/ex1.py new file mode 100755 index 0000000..4abe858 --- /dev/null +++ b/2019/d25/ex1/ex1.py @@ -0,0 +1,486 @@ +#!/usr/bin/env python + +import itertools +import sys +from collections import deque +from copy import deepcopy +from dataclasses import dataclass, field +from enum import IntEnum, StrEnum +from typing import List, NamedTuple + + +class ParameterMode(IntEnum): + POSITION = 0 # Acts on address + IMMEDIATE = 1 # Acts on the immediate value + RELATIVE = 2 # Acts on offset to relative base + + +class Instruction(NamedTuple): + address: int # The address of the instruction, for convenience + op: int # The opcode + p1_mode: ParameterMode # Which mode is the first parameter in + p2_mode: ParameterMode # Which mode is the second parameter in + p3_mode: ParameterMode # Which mode is the third parameter in + + +def lookup_ops(index: int, memory: List[int]) -> Instruction: + digits = list(map(int, str(memory[index]))) + a, b, c, d, e = [0] * (5 - len(digits)) + digits # Pad with default values + return Instruction( + address=index, + op=d * 10 + e, + p1_mode=ParameterMode(c), + p2_mode=ParameterMode(b), + p3_mode=ParameterMode(a), + ) + + +class InputInterrupt(Exception): + pass + + +class OutputInterrupt(Exception): + pass + + +@dataclass +class Computer: + memory: List[int] # Memory space + rip: int = 0 # Instruction pointer + input_list: List[int] = field(default_factory=list) + output_list: List[int] = field(default_factory=list) + is_halted: bool = field(default=False, init=False) + relative_base: int = field(default=0, init=False) + + def run(self) -> None: + while not self.is_halted: + self.run_single() + + def run_no_output_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_single() + except OutputInterrupt: + continue + + def run_until_input_interrupt(self) -> None: + while not self.is_halted: + try: + self.run_no_output_interrupt() + except InputInterrupt: + return + + def run_single(self) -> None: # Returns True when halted + instr = lookup_ops(self.rip, self.memory) + if instr.op == 99: # Halt + self.is_halted = True + elif instr.op == 1: # Sum + self._do_addition(instr) + elif instr.op == 2: # Multiplication + self._do_multiplication(instr) + elif instr.op == 3: # Load from input + self._do_input(instr) + elif instr.op == 4: # Store to output + self._do_output(instr) + elif instr.op == 5: # Jump if true + self._do_jump_if_true(instr) + elif instr.op == 6: # Jump if false + self._do_jump_if_false(instr) + elif instr.op == 7: # Less than + self._do_less_than(instr) + elif instr.op == 8: # Equal to + self._do_equal_to(instr) + elif instr.op == 9: # Change relative base + self._do_change_relative_base(instr) + else: + assert False # Sanity check + + def _fill_to_addres(self, address: int) -> None: + values = address - len(self.memory) + 1 + if values <= 0: + return + for __ in range(values): + self.memory.append(0) + + def _get_value(self, mode: ParameterMode, val: int) -> int: + if mode == ParameterMode.POSITION: + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + elif mode == ParameterMode.RELATIVE: + val += self.relative_base + assert 0 <= val # Sanity check + self._fill_to_addres(val) + return self.memory[val] + assert mode == ParameterMode.IMMEDIATE # Sanity check + return val + + def _set_value(self, mode: ParameterMode, address: int, value: int) -> None: + if mode == ParameterMode.RELATIVE: + address += self.relative_base + else: + assert mode == ParameterMode.POSITION # Sanity check + + assert address >= 0 # Sanity check + self._fill_to_addres(address) + + self.memory[address] = value + + def _do_addition(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs + rhs) + + self.rip += 4 # Length of the instruction + + def _do_multiplication(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, lhs * rhs) + + self.rip += 4 # Length of the instruction + + def _do_input(self, instr: Instruction) -> None: + if len(self.input_list) == 0: + raise InputInterrupt # No input, halt until an input is provided + + value = int(self.input_list.pop(0)) + param = self.memory[instr.address + 1] + + self._set_value(instr.p1_mode, param, value) + + self.rip += 2 # Length of the instruction + + def _do_output(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.output_list.append(value) + + self.rip += 2 # Length of the instruction + raise OutputInterrupt # Alert that we got an output to give + + def _do_jump_if_true(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond != 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_jump_if_false(self, instr: Instruction) -> None: + cond = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + value = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + + if cond == 0: + self.rip = value + else: + self.rip += 3 # Length of the instruction + + def _do_less_than(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs < rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_equal_to(self, instr: Instruction) -> None: + lhs = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + rhs = self._get_value(instr.p2_mode, self.memory[instr.address + 2]) + dest = self.memory[instr.address + 3] + + self._set_value(instr.p3_mode, dest, 1 if lhs == rhs else 0) + + self.rip += 4 # Length of the instruction + + def _do_change_relative_base(self, instr: Instruction) -> None: + value = self._get_value(instr.p1_mode, self.memory[instr.address + 1]) + + self.relative_base += value + self.rip += 2 # Length of the instruction + + +class Move(StrEnum): + NORTH = "north" + SOUTH = "south" + EAST = "east" + WEST = "west" + + def opposite(self) -> "Move": + if self == Move.NORTH: + return Move.SOUTH + if self == Move.SOUTH: + return Move.NORTH + if self == Move.EAST: + return Move.WEST + if self == Move.WEST: + return Move.EAST + assert False # Sanity check + + +@dataclass +class Graph: + nodes: dict[str, dict[Move, str]] = field(default_factory=dict) + explored: set[str] = field(default_factory=set) + + def add_room(self, room: str) -> None: + self.nodes.setdefault(room, {}) + + def add_door(self, room: str, move: Move) -> None: + if move in self.nodes[room]: + return + + other_room = f"{move} of {room}" + self.nodes[room][move] = other_room + self.add_room(other_room) + self.nodes[other_room].setdefault(move.opposite(), room) + + def set_visited(self, room: str) -> None: + self.explored.add(room) + + # FIXME: repetition + def goto(self, start: str, end: str) -> list[Move]: + queue: deque[tuple[str, list[Move]]] = deque([(start, [])]) + visited: set[str] = {start} + + while queue: + room, path = queue.popleft() + visited.add(room) + if room == end: + return path + for dir, neighbour in self.nodes[room].items(): + if neighbour in visited: + continue + queue.append((neighbour, path + [dir])) + + assert False # Sanity check + + def visit_unexplored(self, start: str) -> tuple[str, list[Move]] | None: + queue: deque[tuple[str, list[Move]]] = deque([(start, [])]) + visited: set[str] = {start} + + while queue: + room, path = queue.popleft() + visited.add(room) + if room not in self.explored: + return room, path + for dir, neighbour in self.nodes[room].items(): + if neighbour in visited: + continue + queue.append((neighbour, path + [dir])) + + return None + + def rename(self, old: str, new: str) -> None: + if old == new or old not in self.nodes: + return + + self.nodes[new] = self.nodes.pop(old) + for neighbours in self.nodes.values(): + for move in Move: + if move not in neighbours: + continue + neighbours[move] = new if neighbours[move] == old else neighbours[move] + + if old in self.explored: + self.explored.remove(old) + self.explored.add(new) + + +def get_room_name(output: list[str]) -> str: + for line in output: + if not line.startswith("== "): + continue + return line.replace("==", "").strip() + assert False # Sanity check + + +def add_doors( + output: list[str], + room: str, + graph: Graph, +) -> None: + DOORS_LEAD = "Doors here lead:" + + if DOORS_LEAD not in output: + return + + doors_lead_index = output.index(DOORS_LEAD) + doors_lead_end = output.index("", doors_lead_index) + directions = [ + Move(line.removeprefix("- ")) + for line in output[doors_lead_index:doors_lead_end] + if line.startswith("- ") + ] + + for dir in directions: + graph.add_door(room, dir) + + +def gather_items_in_room( + output: list[str], +) -> list[str]: + ITEMS_HERE = "Items here:" + # XXX: hard-coded list of items + CURSED_ITEMS = { + "escape pod", + "giant electromagnet", + "infinite loop", + "molten lava", + "photons", + } + + if ITEMS_HERE not in output: + return [] + + items_here_index = output.index(ITEMS_HERE) + items_here_end = output.index("", items_here_index) + items = [ + line.removeprefix("- ") + for line in output[items_here_index:items_here_end] + if line.startswith("- ") + ] + return [f"take {item}" for item in items if item not in CURSED_ITEMS] + + +def explore_rooms( + output: list[str], + room: str, + graph: Graph, +) -> tuple[str, list[str], bool]: + SECURITY = "Security Checkpoint" + + # Commands we want to execute + commands: list[str] = [] + + # Get the actual room name, and fix the graph to refer to it + actual_room = get_room_name(output) + graph.rename(room, actual_room) + room = actual_room + + # Mark this room as visited + graph.set_visited(room) + + # Add new doors to graph, except security checkpoint which won't let us through + if room != SECURITY: + add_doors(output, room, graph) + + # Gather items in room + commands += gather_items_in_room(output) + + # Go to an unexplored room if possible + if (res := graph.visit_unexplored(room)) is not None: + room, path = res + commands += path + else: + # Go to security room otherwise, with all our items + return SECURITY, list(map(str, graph.goto(room, SECURITY))), False + + return room, commands, True + + +def get_last_output(droid: Computer) -> list[str]: + output = "".join(map(chr, droid.output_list)) + droid.output_list.clear() + res: list[str] = [] + for line in output.splitlines()[::-1]: + res.append(line) + if line.startswith("== "): + break + return res[::-1] + + +def gather_items(droid: Computer) -> Computer: + # Avoid changing the input droid + droid = deepcopy(droid) + + room = "Starting room" + graph = Graph() + graph.add_room(room) + + needs_items = True + while needs_items: + droid.run_until_input_interrupt() + output = get_last_output(droid) + room, commands, needs_items = explore_rooms(output, room, graph) + commands.append("") # Account for final new-line + droid.input_list.extend(map(ord, "\n".join(commands))) + + # Finish going back to security + droid.run_until_input_interrupt() + # And drain last output + get_last_output(droid) + + return droid + + +def get_current_items(droid: Computer) -> set[str]: + # Avoid changing the input droid + droid = deepcopy(droid) + + assert not droid.input_list # Sanity check + assert not droid.output_list # Sanity check + + droid.input_list = list(map(ord, "inv\n")) + droid.run_until_input_interrupt() + return { + line.removeprefix("- ") + for line in "".join(map(chr, droid.output_list)).splitlines() + if line.startswith("- ") + } + + +def go_through_security(droid: Computer) -> Computer: + items = get_current_items(droid) + + for r in range(0, len(items)): + for keep in itertools.combinations(items, r): + drop = items - set(keep) + + # Try on a temporary droid, use `droid` as a save point + tmp_droid = deepcopy(droid) + tmp_droid.input_list.extend( + map(ord, "".join(f"drop {item}\n" for item in drop)) + ) + # XXX: hard-coded direction of final room + tmp_droid.input_list.extend(map(ord, "west\n")) + + try: + tmp_droid.run_no_output_interrupt() + except InputInterrupt: + # This set of items failed, try again + continue + # We halted, return the droid + return tmp_droid + + assert False + + +def solve(input_str: str) -> int: + memory = [int(n) for n in input_str.split(",")] + droid = Computer(memory) + + # Explore the ship and gather all items + droid = gather_items(droid) + + # Go through checkpoint weight plate + droid = go_through_security(droid) + + final_output = "".join(map(chr, droid.output_list)) + # Most terrible parsing of the year + return int(final_output.splitlines()[-1].split("typing ")[1].split()[0]) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main() diff --git a/2019/d25/ex1/input b/2019/d25/ex1/input new file mode 100644 index 0000000..86d6542 --- /dev/null +++ b/2019/d25/ex1/input @@ -0,0 +1 @@ +109,4811,21101,3124,0,1,21101,0,13,0,1106,0,1424,21102,166,1,1,21101,24,0,0,1106,0,1234,21102,31,1,0,1106,0,1984,1105,1,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,22102,1,-2,2,21101,0,1162,0,2105,1,-3,21201,-2,1,-2,1105,1,1136,109,-7,2106,0,0,109,6,1202,-5,1,1182,20102,1,0,-2,21102,0,1,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1205,20101,0,0,1,22101,0,-3,2,22102,1,-2,3,21102,1,1222,0,2106,0,-4,21201,-3,1,-3,1105,1,1192,109,-6,2106,0,0,109,2,21201,-1,0,1,21102,1,1256,2,21101,1251,0,0,1105,1,1174,109,-2,2105,1,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,2102,1,-2,1280,1006,0,1303,104,45,104,32,1201,-1,66,1292,20102,1,0,1,21102,1,1301,0,1106,0,1234,104,10,109,-3,2106,0,0,0,0,109,2,2102,1,-1,1309,1102,0,1,1308,21101,4601,0,1,21101,0,13,2,21101,4,0,3,21102,1353,1,4,21101,1343,0,0,1106,0,1130,21001,1308,0,-1,109,-2,2105,1,0,85,109,3,2101,0,-2,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1101,0,1,1308,21008,1309,-1,-1,1206,-1,1387,21101,106,0,1,1106,0,1391,21102,92,1,1,21102,1,1398,0,1105,1,1234,104,45,104,32,1201,-2,1,1407,21001,0,0,1,21101,0,1417,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,2102,1,-2,1128,21101,34,0,1,21101,1441,0,0,1106,0,1234,1001,1128,0,1447,20102,1,0,1,21101,0,1456,0,1105,1,1234,21102,1,41,1,21101,1467,0,0,1106,0,1234,1001,1128,1,1472,21002,0,1,1,21102,1,1482,0,1105,1,1234,21101,0,46,1,21102,1493,1,0,1105,1,1234,21001,1128,3,1,21102,1,4,2,21102,1,1,3,21102,1,1273,4,21102,1,1516,0,1106,0,1130,21002,1128,1,1,21101,0,1527,0,1105,1,1310,1001,1128,2,1532,21001,0,0,-1,1206,-1,1545,21101,1545,0,0,2106,0,-1,109,-3,2106,0,0,109,0,99,109,2,1101,0,0,1550,21101,0,4601,1,21102,13,1,2,21101,4,0,3,21101,1664,0,4,21102,1,1582,0,1106,0,1130,2,2486,1352,1551,1101,0,0,1552,21002,1550,1,1,21101,33,0,2,21101,0,1702,3,21102,1609,1,0,1106,0,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1,1630,0,1106,0,1752,21102,548,1,1,1105,1,1641,21102,687,1,1,21101,1648,0,0,1106,0,1234,21101,0,4457,1,21101,1659,0,0,1106,0,1424,109,-2,2106,0,0,109,4,21202,-2,-1,-2,2101,0,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1716,21001,0,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1101,-1,0,1552,1105,1,1747,22007,1551,-2,-1,1205,-1,1747,1101,1,0,1552,109,-5,2105,1,0,109,1,21101,0,826,1,21102,1765,1,0,1105,1,1234,21001,1550,0,1,21101,0,1776,0,1105,1,2863,21101,0,1090,1,21102,1,1787,0,1106,0,1234,99,1106,0,1787,109,-1,2106,0,0,109,1,21101,512,0,1,21101,0,1809,0,1106,0,1234,99,1106,0,1809,109,-1,2106,0,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21101,377,0,1,21101,0,1842,0,1105,1,1234,1106,0,1831,109,-1,2105,1,0,109,1,21101,0,407,1,21101,0,1863,0,1106,0,1234,99,1106,0,1863,109,-1,2106,0,0,109,1,21101,452,0,1,21101,0,1885,0,1106,0,1234,99,1106,0,1885,109,-1,2106,0,0,1941,1947,1953,1958,1965,1972,1978,4914,5079,5161,5112,5374,5315,5121,4944,5464,5331,4939,4752,5423,4875,4966,4835,5049,5360,5209,5290,4802,4942,5478,4940,5205,4784,4786,5442,5228,5053,4853,5462,5027,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21102,1,1993,0,1105,1,2634,1006,1129,2010,21101,316,0,1,21101,2007,0,0,1105,1,1234,1106,0,2076,21101,0,0,-1,1201,-1,1894,2019,21002,0,1,1,21101,0,0,2,21101,0,0,3,21102,2037,1,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21102,1,2051,0,105,1,0,1106,0,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21102,2076,1,0,1105,1,1234,109,-3,2105,1,0,109,3,2001,1128,-2,2088,21001,0,0,-1,1205,-1,2108,21102,201,1,1,21102,2105,1,0,1106,0,1234,1106,0,2119,22101,0,-1,1,21101,2119,0,0,1106,0,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,4601,0,1,21102,13,1,2,21102,1,4,3,21102,1,2173,4,21101,2154,0,0,1106,0,1130,1005,2124,2168,21102,1,226,1,21101,2168,0,0,1105,1,1234,109,-1,2106,0,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20101,0,0,-1,22102,1,-1,1,21101,5,0,2,21102,1,1,3,21102,2216,1,0,1105,1,2525,1206,1,2275,21102,258,1,1,21101,0,2230,0,1106,0,1234,22101,0,-1,1,21101,0,2241,0,1105,1,1234,104,46,104,10,1101,1,0,2124,1201,-2,0,2256,1102,-1,1,0,1201,-2,3,2262,21001,0,0,-1,1206,-1,2275,21101,2275,0,0,2105,1,-1,109,-3,2106,0,0,0,109,1,1101,0,0,2280,21102,4601,1,1,21102,13,1,2,21102,1,4,3,21101,0,2329,4,21101,0,2310,0,1106,0,1130,1005,2280,2324,21102,273,1,1,21102,1,2324,0,1105,1,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2351,20102,1,0,-1,22101,0,-1,1,21102,5,1,2,21102,1,1,3,21102,1,2372,0,1106,0,2525,1206,1,2413,21102,301,1,1,21101,0,2386,0,1106,0,1234,21202,-1,1,1,21102,1,2397,0,1106,0,1234,104,46,104,10,1101,0,1,2280,1201,-2,0,2412,102,1,1128,0,109,-3,2105,1,0,109,1,21102,-1,1,1,21102,1,2431,0,1105,1,1310,1205,1,2445,21102,133,1,1,21102,2445,1,0,1106,0,1234,109,-1,2105,1,0,109,1,21102,3,1,1,21101,0,2463,0,1105,1,2081,109,-1,2105,1,0,109,1,21102,4,1,1,21102,1,2481,0,1105,1,2081,109,-1,2105,1,0,64,109,1,21102,1,5,1,21101,2500,0,0,1105,1,2081,109,-1,2106,0,0,109,1,21102,1,6,1,21101,0,2518,0,1106,0,2081,109,-1,2105,1,0,0,0,109,5,2102,1,-3,2523,1102,1,1,2524,22101,0,-4,1,21101,0,2585,2,21101,2550,0,0,1106,0,1174,1206,-2,2576,1202,-4,1,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1101,0,0,2524,21002,2524,1,-4,109,-5,2106,0,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21101,0,-1,-4,201,-3,2523,2615,1001,2615,3094,2615,21001,0,0,-1,22208,-4,-1,-1,1205,-1,2629,1102,1,0,2524,109,-5,2105,1,0,109,4,21102,3094,1,1,21102,30,1,2,21102,1,1,3,21101,2706,0,4,21101,0,2659,0,1106,0,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,1201,-2,0,0,21201,-3,1,-3,1105,1,2663,109,-4,2105,1,0,109,2,2101,0,-1,2715,1101,0,-1,0,109,-2,2106,0,0,0,109,5,2101,0,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,0,1,-4,21202,-4,1,1,22101,0,-3,2,21101,1,0,3,21101,0,2758,0,1106,0,2763,109,-5,2105,1,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,22101,0,-5,-5,1105,1,2858,21201,-5,0,1,21201,-4,-1,2,21202,-3,2,3,21101,2805,0,0,1106,0,2763,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,21202,-2,1,1,21201,-4,-1,2,21101,2850,0,0,106,0,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1105,1,2888,104,45,21202,-2,-1,-2,22101,0,-2,1,21101,0,2899,0,1106,0,2909,1105,1,2904,104,48,109,-3,2106,0,0,109,4,21201,-3,0,1,21102,1,10,2,21102,1,2926,0,1106,0,3010,22102,1,1,-2,21201,2,0,-1,1206,-2,2948,21202,-2,1,1,21101,0,2948,0,1105,1,2909,22101,48,-1,-1,204,-1,109,-4,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21101,0,0,-4,21101,0,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,2959,3034,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,21202,-3,1,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,0,3584,4000,3252,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3268,0,3341,3124,3433,0,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3348,3356,0,3488,3833,3252,0,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3440,3447,0,3252,3768,3695,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,3495,3504,0,4180,0,3341,0,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,3591,3612,0,0,3653,0,3124,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3660,3668,0,0,0,0,3584,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,3702,3711,0,3433,0,0,0,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3775,3798,0,0,3904,4332,3433,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,3840,3852,0,0,0,0,3341,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,3911,3922,0,0,4057,4121,3768,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4007,4021,0,3124,4252,0,0,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,4064,4072,0,0,0,4382,3904,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,4128,4151,0,3904,0,0,0,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,4187,4196,0,0,0,3488,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4259,4271,0,0,0,0,4000,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,4339,4347,0,3768,0,0,0,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,4389,4401,0,4057,0,4457,0,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,4464,4484,0,4382,0,0,4556,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,4457,0,0,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,4121,4653,27,1872,3433,4661,28,1818,4057,4681,1053,0,3768,4706,30,1796,3833,4717,33,0,3653,4729,32,1850,3695,4741,262177,0,3488,4752,34,1829,3584,4766,67,0,4000,4771,67108900,0,4382,4780,524325,0,4180,4790,268435494,0,3341,4804,16777255,0,7,105,96,102,106,100,98,102,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,24,91,87,71,72,73,3,78,66,87,-1,81,77,61,62,63,-7,58,73,69,56,60,72,68,54,10,91,104,87,84,98,86,16,95,93,81,11,91,93,107,87,85,16,95,93,86,90,95,11,98,99,95,102,86,94,15,90,78,98,76,10,89,86,98,87,107,17,83,80,92,82,13,92,96,87,89,93,87,97,81,11,86,88,87,87,4,111,92,104,93,8,103,105,100,86,97,88,96,101,9,93,107,90,96,19,85,86,92,91,13,102,98,96,95,91,14,92,82,11,77,74,92,29,6,113,107,93,88,106,93 diff --git a/2019/d25/ex2/ex2.py b/2019/d25/ex2/ex2.py new file mode 100755 index 0000000..918e0ec --- /dev/null +++ b/2019/d25/ex2/ex2.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python + + +def main() -> None: + print("There is no part two...") + + +if __name__ == "__main__": + main() diff --git a/2019/d25/ex2/input b/2019/d25/ex2/input new file mode 100644 index 0000000..86d6542 --- /dev/null +++ b/2019/d25/ex2/input @@ -0,0 +1 @@ +109,4811,21101,3124,0,1,21101,0,13,0,1106,0,1424,21102,166,1,1,21101,24,0,0,1106,0,1234,21102,31,1,0,1106,0,1984,1105,1,13,6,4,3,2,52,51,21,4,28,56,55,3,19,-9,-10,47,89,88,90,90,6,77,73,85,71,1,76,68,63,65,22,-27,70,76,81,87,5,105,105,107,108,95,4,97,92,109,109,5,110,105,110,108,95,4,115,96,109,109,13,-3,59,101,85,92,97,13,84,80,92,78,34,-15,26,-16,46,88,72,79,84,0,72,76,-3,85,74,79,75,-8,64,68,75,57,65,70,64,66,72,8,-41,32,-22,56,77,82,-4,60,76,62,70,-2,74,-11,55,52,68,67,73,56,60,52,-20,44,56,66,-24,48,58,42,49,54,-16,-53,10,0,56,99,96,95,82,94,83,45,-9,23,-13,61,85,88,74,71,82,73,79,73,89,67,65,-4,62,73,70,69,56,68,57,2,-35,24,-14,64,85,90,4,70,67,79,7,83,-2,68,75,-5,78,65,57,75,-10,76,53,76,0,-37,31,-21,57,78,83,-3,64,74,72,0,76,-9,73,58,57,-13,70,57,49,67,-18,54,64,48,55,-23,48,44,56,42,-14,-51,14,-4,74,95,100,14,97,77,86,79,9,92,79,75,5,27,-17,61,82,87,1,68,78,76,4,80,-5,66,58,78,60,-10,73,60,52,70,-15,57,67,51,58,-6,-43,14,-4,74,95,100,14,81,94,90,90,9,92,79,75,5,60,-50,23,42,38,-32,38,39,30,42,47,-38,30,36,28,25,41,38,34,31,18,23,29,19,33,-52,20,29,-55,27,27,27,8,15,-61,22,16,-64,24,13,18,-54,-69,-70,-14,7,12,-74,-8,-11,1,-71,5,-80,-4,-3,3,-15,-84,-85,-109,29,-19,59,80,85,-1,82,62,71,64,-6,77,64,60,-10,62,66,57,59,63,57,67,51,-19,56,58,57,57,-10,-47,44,-34,39,58,54,-16,60,61,57,64,48,56,-23,52,40,60,38,-28,44,53,-31,55,32,55,-35,48,42,41,-39,32,38,42,-42,-44,12,33,38,-48,28,19,25,32,-52,-76,-77,59,-49,13,55,-30,42,51,-33,49,50,32,31,31,39,36,48,-42,24,35,32,34,29,21,35,19,25,37,-53,14,10,26,18,-57,-59,-3,18,23,-63,1,17,3,-67,1,-4,14,-2,6,-73,-8,14,-76,-12,-78,-40,2,4,-13,-82,-106,-107,35,-25,53,74,79,0,74,60,-10,65,53,72,64,52,56,52,50,-19,53,57,62,56,-24,58,54,38,39,40,-29,-31,2,56,35,-34,-58,-59,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-94,-98,-103,-83,-97,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,138,-128,-74,-108,-33,-31,-26,-44,-101,-114,-33,-37,-51,-39,-35,-47,-54,-122,-37,-45,-52,-59,-58,-128,-46,-65,-42,-49,-133,-132,-102,-60,-68,-56,-55,-139,-141,-106,-61,-65,-72,-78,-64,-148,-70,-72,-151,-68,-81,-81,-72,-156,-74,-86,-86,-80,-161,-97,-81,-95,-165,-90,-94,-97,-97,-86,-102,-90,-173,-90,-103,-111,-99,-178,-95,-108,-112,-182,-115,-115,-101,-117,-120,-104,-120,-122,-191,-106,-128,-118,-110,-127,-196,-196,-199,-135,-123,-134,-203,-115,-126,-121,-207,-143,-127,-141,-211,-143,-139,-145,-148,-132,-148,-150,-219,-154,-156,-155,-148,-224,-141,-147,-227,-144,-157,-161,-231,-165,-161,-165,-168,-161,-157,-159,-166,-162,-157,-228,-265,263,-253,-199,-233,-158,-156,-151,-169,-226,-239,-158,-162,-176,-164,-160,-172,-179,-247,-162,-170,-177,-184,-183,-253,-171,-190,-167,-174,-258,-257,-227,-183,-197,-187,-175,-182,-193,-184,-268,-202,-191,-194,-192,-197,-205,-191,-207,-276,-278,-222,-201,-196,-282,-206,-219,-196,-286,-207,-206,-210,-223,-222,-223,-225,-280,-293,-296,-232,-220,-231,-300,-212,-223,-218,-304,-236,-228,-223,-239,-227,-310,-227,-240,-244,-314,-248,-237,-250,-243,-239,-247,-237,-308,-345,-273,-260,-248,-243,-263,-329,-252,-252,-248,-260,-267,-266,-253,-337,-249,-260,-255,-259,-342,-260,-267,-280,-270,-271,-348,-281,-268,-272,-279,-285,-342,-355,-280,-278,-279,-284,-277,-361,-282,-278,-274,-275,-290,-298,-300,-369,-300,-292,-290,-373,-309,-375,-299,-298,-301,-310,-302,-297,-370,-383,-302,-316,-321,-311,-315,-299,-321,-308,-392,-306,-322,-330,-312,-397,-326,-334,-317,-401,-330,-338,-324,-325,-337,-329,-339,-341,-398,-411,-347,-335,-346,-415,-334,-352,-350,-346,-341,-338,-422,-334,-345,-340,-344,-427,-345,-357,-357,-351,-432,-365,-361,-353,-367,-370,-354,-363,-351,-427,-464,-441,-397,-373,-434,-447,-376,-380,-374,-375,-373,-452,-454,-398,-377,-372,-458,-376,-388,-382,-377,-387,-396,-465,-400,-398,-468,-404,-404,-395,-403,-473,-390,-396,-476,-406,-409,-395,-480,-408,-404,-483,-418,-396,-486,-403,-399,-409,-417,-413,-421,-493,37,-5,73,71,-8,75,62,58,-12,62,55,74,64,48,50,-19,45,63,-22,61,48,44,-26,50,37,44,48,-31,33,40,48,41,43,30,37,-25,-38,-63,0,0,109,7,21101,0,0,-2,22208,-2,-5,-1,1205,-1,1169,22202,-2,-4,1,22201,1,-6,1,22102,1,-2,2,21101,0,1162,0,2105,1,-3,21201,-2,1,-2,1105,1,1136,109,-7,2106,0,0,109,6,1202,-5,1,1182,20102,1,0,-2,21102,0,1,-3,21201,-5,1,-5,22208,-3,-2,-1,1205,-1,1229,2201,-5,-3,1205,20101,0,0,1,22101,0,-3,2,22102,1,-2,3,21102,1,1222,0,2106,0,-4,21201,-3,1,-3,1105,1,1192,109,-6,2106,0,0,109,2,21201,-1,0,1,21102,1,1256,2,21101,1251,0,0,1105,1,1174,109,-2,2105,1,0,109,5,22201,-4,-3,-1,22201,-2,-1,-1,204,-1,109,-5,2106,0,0,109,3,2102,1,-2,1280,1006,0,1303,104,45,104,32,1201,-1,66,1292,20102,1,0,1,21102,1,1301,0,1106,0,1234,104,10,109,-3,2106,0,0,0,0,109,2,2102,1,-1,1309,1102,0,1,1308,21101,4601,0,1,21101,0,13,2,21101,4,0,3,21102,1353,1,4,21101,1343,0,0,1106,0,1130,21001,1308,0,-1,109,-2,2105,1,0,85,109,3,2101,0,-2,1360,20008,0,1309,-1,1206,-1,1419,1005,1308,1398,1101,0,1,1308,21008,1309,-1,-1,1206,-1,1387,21101,106,0,1,1106,0,1391,21102,92,1,1,21102,1,1398,0,1105,1,1234,104,45,104,32,1201,-2,1,1407,21001,0,0,1,21101,0,1417,0,1105,1,1234,104,10,109,-3,2105,1,0,109,3,2102,1,-2,1128,21101,34,0,1,21101,1441,0,0,1106,0,1234,1001,1128,0,1447,20102,1,0,1,21101,0,1456,0,1105,1,1234,21102,1,41,1,21101,1467,0,0,1106,0,1234,1001,1128,1,1472,21002,0,1,1,21102,1,1482,0,1105,1,1234,21101,0,46,1,21102,1493,1,0,1105,1,1234,21001,1128,3,1,21102,1,4,2,21102,1,1,3,21102,1,1273,4,21102,1,1516,0,1106,0,1130,21002,1128,1,1,21101,0,1527,0,1105,1,1310,1001,1128,2,1532,21001,0,0,-1,1206,-1,1545,21101,1545,0,0,2106,0,-1,109,-3,2106,0,0,109,0,99,109,2,1101,0,0,1550,21101,0,4601,1,21102,13,1,2,21101,4,0,3,21101,1664,0,4,21102,1,1582,0,1106,0,1130,2,2486,1352,1551,1101,0,0,1552,21002,1550,1,1,21101,33,0,2,21101,0,1702,3,21102,1609,1,0,1106,0,2722,21007,1552,0,-1,1205,-1,1630,20107,0,1552,-1,1205,-1,1637,21102,1,1630,0,1106,0,1752,21102,548,1,1,1105,1,1641,21102,687,1,1,21101,1648,0,0,1106,0,1234,21101,0,4457,1,21101,1659,0,0,1106,0,1424,109,-2,2106,0,0,109,4,21202,-2,-1,-2,2101,0,-3,1675,21008,0,-1,-1,1206,-1,1697,1201,-3,2,1687,20101,-27,0,-3,22201,-3,-2,-3,2001,1550,-3,1550,109,-4,2105,1,0,109,5,21008,1552,0,-1,1206,-1,1747,1201,-3,1901,1716,21001,0,0,-2,1205,-4,1736,20207,-2,1551,-1,1205,-1,1747,1101,-1,0,1552,1105,1,1747,22007,1551,-2,-1,1205,-1,1747,1101,1,0,1552,109,-5,2105,1,0,109,1,21101,0,826,1,21102,1765,1,0,1105,1,1234,21001,1550,0,1,21101,0,1776,0,1105,1,2863,21101,0,1090,1,21102,1,1787,0,1106,0,1234,99,1106,0,1787,109,-1,2106,0,0,109,1,21101,512,0,1,21101,0,1809,0,1106,0,1234,99,1106,0,1809,109,-1,2106,0,0,109,1,1102,1,1,1129,109,-1,2106,0,0,109,1,21101,377,0,1,21101,0,1842,0,1105,1,1234,1106,0,1831,109,-1,2105,1,0,109,1,21101,0,407,1,21101,0,1863,0,1106,0,1234,99,1106,0,1863,109,-1,2106,0,0,109,1,21101,452,0,1,21101,0,1885,0,1106,0,1234,99,1106,0,1885,109,-1,2106,0,0,1941,1947,1953,1958,1965,1972,1978,4914,5079,5161,5112,5374,5315,5121,4944,5464,5331,4939,4752,5423,4875,4966,4835,5049,5360,5209,5290,4802,4942,5478,4940,5205,4784,4786,5442,5228,5053,4853,5462,5027,2281,2468,2418,2450,2487,2125,2505,5,95,108,104,104,23,5,96,91,108,108,1,4,101,105,112,3,6,104,104,106,107,94,-1,6,109,104,109,107,94,-1,5,111,91,100,93,23,5,114,95,108,108,1,109,3,21102,1,1993,0,1105,1,2634,1006,1129,2010,21101,316,0,1,21101,2007,0,0,1105,1,1234,1106,0,2076,21101,0,0,-1,1201,-1,1894,2019,21002,0,1,1,21101,0,0,2,21101,0,0,3,21102,2037,1,0,1106,0,2525,1206,1,2054,1201,-1,1934,2050,21102,1,2051,0,105,1,0,1106,0,2076,21201,-1,1,-1,21207,-1,7,-2,1205,-2,2014,21101,0,177,1,21102,2076,1,0,1105,1,1234,109,-3,2105,1,0,109,3,2001,1128,-2,2088,21001,0,0,-1,1205,-1,2108,21102,201,1,1,21102,2105,1,0,1106,0,1234,1106,0,2119,22101,0,-1,1,21101,2119,0,0,1106,0,1424,109,-3,2105,1,0,0,109,1,1101,0,0,2124,21101,4601,0,1,21102,13,1,2,21102,1,4,3,21102,1,2173,4,21101,2154,0,0,1106,0,1130,1005,2124,2168,21102,1,226,1,21101,2168,0,0,1105,1,1234,109,-1,2106,0,0,109,3,1005,2124,2275,1201,-2,0,2183,20008,0,1128,-1,1206,-1,2275,1201,-2,1,2195,20101,0,0,-1,22102,1,-1,1,21101,5,0,2,21102,1,1,3,21102,2216,1,0,1105,1,2525,1206,1,2275,21102,258,1,1,21101,0,2230,0,1106,0,1234,22101,0,-1,1,21101,0,2241,0,1105,1,1234,104,46,104,10,1101,1,0,2124,1201,-2,0,2256,1102,-1,1,0,1201,-2,3,2262,21001,0,0,-1,1206,-1,2275,21101,2275,0,0,2105,1,-1,109,-3,2106,0,0,0,109,1,1101,0,0,2280,21102,4601,1,1,21102,13,1,2,21102,1,4,3,21101,0,2329,4,21101,0,2310,0,1106,0,1130,1005,2280,2324,21102,273,1,1,21102,1,2324,0,1105,1,1234,109,-1,2105,1,0,109,3,1005,2280,2413,1201,-2,0,2339,21008,0,-1,-1,1206,-1,2413,1201,-2,1,2351,20102,1,0,-1,22101,0,-1,1,21102,5,1,2,21102,1,1,3,21102,1,2372,0,1106,0,2525,1206,1,2413,21102,301,1,1,21101,0,2386,0,1106,0,1234,21202,-1,1,1,21102,1,2397,0,1106,0,1234,104,46,104,10,1101,0,1,2280,1201,-2,0,2412,102,1,1128,0,109,-3,2105,1,0,109,1,21102,-1,1,1,21102,1,2431,0,1105,1,1310,1205,1,2445,21102,133,1,1,21102,2445,1,0,1106,0,1234,109,-1,2105,1,0,109,1,21102,3,1,1,21101,0,2463,0,1105,1,2081,109,-1,2105,1,0,109,1,21102,4,1,1,21102,1,2481,0,1105,1,2081,109,-1,2105,1,0,64,109,1,21102,1,5,1,21101,2500,0,0,1105,1,2081,109,-1,2106,0,0,109,1,21102,1,6,1,21101,0,2518,0,1106,0,2081,109,-1,2105,1,0,0,0,109,5,2102,1,-3,2523,1102,1,1,2524,22101,0,-4,1,21101,0,2585,2,21101,2550,0,0,1106,0,1174,1206,-2,2576,1202,-4,1,2558,2001,0,-3,2566,101,3094,2566,2566,21008,0,-1,-1,1205,-1,2576,1101,0,0,2524,21002,2524,1,-4,109,-5,2106,0,0,109,5,22201,-4,-3,-4,22201,-4,-2,-4,21208,-4,10,-1,1206,-1,2606,21101,0,-1,-4,201,-3,2523,2615,1001,2615,3094,2615,21001,0,0,-1,22208,-4,-1,-1,1205,-1,2629,1102,1,0,2524,109,-5,2105,1,0,109,4,21102,3094,1,1,21102,30,1,2,21102,1,1,3,21101,2706,0,4,21101,0,2659,0,1106,0,1130,21101,0,0,-3,203,-2,21208,-2,10,-1,1205,-1,2701,21207,-2,0,-1,1205,-1,2663,21207,-3,29,-1,1206,-1,2663,2101,3094,-3,2693,1201,-2,0,0,21201,-3,1,-3,1105,1,2663,109,-4,2105,1,0,109,2,2101,0,-1,2715,1101,0,-1,0,109,-2,2106,0,0,0,109,5,2101,0,-2,2721,21207,-4,0,-1,1206,-1,2739,21102,0,1,-4,21202,-4,1,1,22101,0,-3,2,21101,1,0,3,21101,0,2758,0,1106,0,2763,109,-5,2105,1,0,109,6,21207,-4,1,-1,1206,-1,2786,22207,-5,-3,-1,1206,-1,2786,22101,0,-5,-5,1105,1,2858,21201,-5,0,1,21201,-4,-1,2,21202,-3,2,3,21101,2805,0,0,1106,0,2763,22102,1,1,-5,21102,1,1,-2,22207,-5,-3,-1,1206,-1,2824,21102,0,1,-2,22202,-3,-2,-3,22107,0,-4,-1,1206,-1,2850,21202,-2,1,1,21201,-4,-1,2,21101,2850,0,0,106,0,2721,21202,-3,-1,-3,22201,-5,-3,-5,109,-6,2106,0,0,109,3,21208,-2,0,-1,1205,-1,2902,21207,-2,0,-1,1205,-1,2882,1105,1,2888,104,45,21202,-2,-1,-2,22101,0,-2,1,21101,0,2899,0,1106,0,2909,1105,1,2904,104,48,109,-3,2106,0,0,109,4,21201,-3,0,1,21102,1,10,2,21102,1,2926,0,1106,0,3010,22102,1,1,-2,21201,2,0,-1,1206,-2,2948,21202,-2,1,1,21101,0,2948,0,1105,1,2909,22101,48,-1,-1,204,-1,109,-4,2105,1,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,33554432,67108864,134217728,268435456,536870912,1073741824,2147483648,4294967296,8589934592,17179869184,34359738368,68719476736,137438953472,274877906944,549755813888,1099511627776,2199023255552,4398046511104,8796093022208,17592186044416,35184372088832,70368744177664,140737488355328,281474976710656,562949953421312,1125899906842624,109,8,21101,0,0,-4,21101,0,0,-3,21101,0,51,-2,21201,-2,-1,-2,1201,-2,2959,3034,20101,0,0,-1,21202,-3,2,-3,22207,-7,-1,-5,1205,-5,3059,21201,-3,1,-3,22102,-1,-1,-5,22201,-7,-5,-7,22207,-3,-6,-5,1205,-5,3078,22102,-1,-6,-5,22201,-3,-5,-3,22201,-1,-4,-4,1205,-2,3024,21202,-4,1,-7,21202,-3,1,-6,109,-8,2106,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3131,3143,0,0,3584,4000,3252,11,61,105,95,94,17,50,97,83,78,79,83,108,-19,2,7,-79,-9,-2,2,-83,-11,-7,-86,-3,-16,-7,-11,-6,-21,-21,-94,-30,-96,-25,-19,-23,-31,-101,-29,-25,-104,-21,-34,-38,-108,-39,-34,-32,-33,-31,-114,-43,-47,-35,-49,-105,-120,-69,-43,-123,-49,-56,-57,-47,-128,-40,-51,-46,-50,-133,-51,-63,-63,-57,-138,-69,-58,-62,-65,-143,-79,-69,-63,-68,-148,-79,-68,-82,-83,-63,-81,-77,-85,-145,-158,-75,-88,-92,-162,-91,-85,-89,-97,-167,-96,-104,-87,-171,-106,-104,-105,-97,-176,-94,-109,-114,-104,-112,-114,-169,3259,3268,0,3341,3124,3433,0,8,75,96,89,96,20,53,83,106,72,11,44,38,37,35,37,38,36,-48,17,29,33,20,-53,-4,14,12,-44,-12,20,23,8,6,-63,-14,4,7,11,0,0,-1,11,-72,4,-5,-7,-3,-10,-5,-1,-11,-81,-17,-5,-16,-85,-4,-18,-17,-4,-14,-26,-10,-93,-12,-26,-23,-19,-30,-30,-31,-19,-102,-26,-35,-37,-33,-40,-35,-31,-41,-97,3348,3356,0,3488,3833,3252,0,7,65,89,99,98,108,85,108,76,8,27,27,36,-48,16,32,18,13,-53,18,10,27,-57,8,10,9,17,-62,16,16,19,7,10,5,21,-1,-3,-72,-3,5,7,-76,6,1,-2,-11,3,-10,-10,-6,-14,-59,-87,1,-10,-5,-84,-10,-24,-94,-21,-11,-14,-14,-99,-22,-22,-18,-103,-23,-20,-33,-23,-39,-109,-27,-26,-30,-44,-114,-28,-44,-52,-34,-105,3440,3447,0,3252,3768,3695,0,6,59,107,91,88,90,90,40,38,70,68,58,-12,66,56,-15,68,55,51,-19,47,44,44,50,54,44,58,56,-28,54,39,38,45,-33,50,44,-36,35,27,47,29,-41,38,36,43,24,36,-33,3495,3504,0,4180,0,3341,0,8,59,102,104,103,93,87,97,99,79,5,24,20,-50,26,17,31,11,21,-56,30,7,17,16,22,-62,2,14,3,-66,17,4,0,-70,6,-3,11,-9,1,-76,-7,-2,0,-1,1,-82,-18,-2,-16,-86,-4,-12,-16,-19,-19,-8,-17,-5,-95,-28,-24,-28,-29,-31,-19,-33,-25,-20,-105,-39,-28,-32,-30,-28,-28,-98,-113,-67,-33,-116,-52,-36,-50,-120,-37,-50,-54,-35,-94,3591,3612,0,0,3653,0,3124,20,51,84,80,93,8,62,88,70,84,83,75,79,71,-1,33,66,74,79,63,75,40,32,70,77,-11,57,63,69,54,-16,51,61,-19,69,58,63,-23,63,57,39,53,-28,51,52,38,51,36,44,49,47,-37,41,39,-40,43,30,26,-44,26,33,-16,3660,3668,0,0,0,0,3584,7,68,97,107,89,93,89,97,26,43,91,73,85,91,85,72,72,76,68,3,78,-6,63,74,60,59,79,57,0,54,67,57,52,50,-5,3702,3711,0,3433,0,0,0,8,64,102,98,100,88,88,85,92,56,27,54,51,42,51,49,39,-31,51,36,35,42,47,-37,46,40,-40,31,23,43,25,-45,30,22,22,35,-50,22,32,-53,25,23,-56,27,14,10,-60,-22,11,2,14,19,-66,-28,14,4,-2,-71,11,-4,10,9,-3,1,-7,-65,3775,3798,0,0,3904,4332,3433,22,65,74,90,87,6,41,86,76,88,70,0,44,63,70,74,79,63,71,57,69,57,58,34,39,81,-4,60,74,73,61,56,72,72,-12,71,65,-15,50,52,-18,68,59,61,53,50,54,46,-26,51,51,53,47,34,44,43,55,-21,3840,3852,0,0,0,0,3341,11,58,98,90,91,95,85,84,96,86,90,82,51,38,59,64,-22,60,45,44,-26,38,-28,58,42,42,52,36,32,44,29,45,30,-39,47,32,42,29,-44,35,30,18,30,34,-50,19,27,29,-54,-4,24,25,15,19,11,7,20,16,9,3,-66,19,-50,-55,3911,3922,0,0,4057,4121,3768,10,68,86,106,92,89,82,100,88,93,91,77,6,38,18,36,36,33,-25,-52,-2,30,27,9,21,10,10,8,-47,-62,-15,12,4,-1,16,1,-69,13,14,8,7,2,14,-76,0,-9,-14,3,4,0,-14,-7,-16,-8,-3,-5,-89,-20,-9,-13,-16,-94,-25,-23,-27,-14,-10,-100,-18,-18,-38,-22,-22,-106,-23,-29,-109,-28,-42,-45,-48,-38,-42,-50,-35,-53,-35,-51,-107,4007,4021,0,3124,4252,0,0,13,54,100,86,103,15,63,98,77,93,94,78,90,90,35,49,68,64,-6,59,61,59,73,-11,53,69,55,-15,49,59,58,-19,64,58,57,-23,59,52,39,49,48,-29,40,48,50,-33,55,44,49,-23,4064,4072,0,0,0,4382,3904,7,76,108,102,104,86,91,88,48,36,55,51,-19,46,58,66,46,59,-25,48,58,55,55,-30,36,47,45,50,30,37,41,-38,38,39,41,27,-43,22,34,42,22,35,-35,-50,-51,-2,16,13,30,26,26,15,27,9,15,27,-49,4128,4151,0,3904,0,0,0,22,50,88,92,7,41,77,83,70,81,77,65,83,67,-3,34,74,79,71,76,56,63,67,28,55,82,79,70,72,78,85,9,-4,68,78,0,75,-9,73,73,61,63,62,-15,71,62,64,56,53,57,49,-9,4187,4196,0,0,0,3488,0,8,72,88,105,104,85,90,87,100,55,29,48,44,63,-20,54,40,-30,34,-32,43,39,49,48,39,31,-39,44,46,31,40,40,44,-46,18,30,19,-50,32,32,12,28,29,17,21,13,-59,24,18,-62,13,15,14,9,-67,-3,7,6,-71,-7,3,-1,0,-7,-63,4259,4271,0,0,0,0,4000,11,68,86,102,87,99,102,80,98,92,94,100,60,24,43,39,51,37,-33,31,47,33,-37,27,-39,30,28,45,-43,40,24,30,22,35,18,29,29,17,30,-27,-55,28,15,11,30,-53,21,7,-63,1,11,10,-67,-2,10,6,13,-3,-5,-74,-7,3,10,0,-67,-80,3,-10,-4,1,-14,-14,-73,4339,4347,0,3768,0,0,0,7,76,108,88,88,97,89,102,34,48,66,69,73,62,62,61,73,3,72,61,77,55,53,-2,-17,34,53,49,68,-15,59,45,-25,39,49,48,-29,39,46,48,51,55,-21,4389,4401,0,4057,0,4457,0,11,72,87,92,87,95,83,84,14,57,77,77,55,34,55,60,-26,56,41,40,-30,38,54,40,34,34,42,30,31,-39,32,28,40,26,-44,34,24,-47,32,33,29,33,27,31,35,25,13,-57,22,20,16,28,15,6,18,-65,2,2,15,4,1,7,-72,14,5,7,-1,-63,4464,4484,0,4382,0,0,4556,19,64,81,78,95,91,81,91,95,5,39,75,71,68,75,79,77,70,74,79,71,2,38,-41,42,29,25,-45,32,22,40,35,-50,31,27,26,23,-43,-56,8,-58,21,22,8,21,20,21,17,3,-54,15,0,8,12,1,11,-1,11,-7,-77,-8,-3,-1,-2,0,-83,3,-12,-10,-11,-88,-3,-21,-9,-19,-23,-5,-95,-7,-18,-13,-17,-100,-28,-34,-34,-26,-21,-33,-23,-19,-95,4563,4588,1553,0,4457,0,0,24,56,89,75,88,87,88,84,70,13,50,67,75,79,68,78,66,78,60,-10,27,64,66,65,67,12,53,97,83,93,105,105,87,91,83,25,24,23,4121,4653,27,1872,3433,4661,28,1818,4057,4681,1053,0,3768,4706,30,1796,3833,4717,33,0,3653,4729,32,1850,3695,4741,262177,0,3488,4752,34,1829,3584,4766,67,0,4000,4771,67108900,0,4382,4780,524325,0,4180,4790,268435494,0,3341,4804,16777255,0,7,105,96,102,106,100,98,102,19,84,85,76,88,93,8,76,82,74,71,87,84,80,77,64,69,75,65,79,24,91,87,71,72,73,3,78,66,87,-1,81,77,61,62,63,-7,58,73,69,56,60,72,68,54,10,91,104,87,84,98,86,16,95,93,81,11,91,93,107,87,85,16,95,93,86,90,95,11,98,99,95,102,86,94,15,90,78,98,76,10,89,86,98,87,107,17,83,80,92,82,13,92,96,87,89,93,87,97,81,11,86,88,87,87,4,111,92,104,93,8,103,105,100,86,97,88,96,101,9,93,107,90,96,19,85,86,92,91,13,102,98,96,95,91,14,92,82,11,77,74,92,29,6,113,107,93,88,106,93