From 366efe0b0d89a11ae59221530efc099b6d8c048f Mon Sep 17 00:00:00 2001 From: AKP Date: Sun, 3 Dec 2023 20:36:31 +0000 Subject: [PATCH] 2023.03 --- challenges/2023/03-gearRatios/README.md | 1 + challenges/2023/03-gearRatios/main.py | 135 +++++++++++++++++++++++ challenges/2023/03-gearRatios/tests.json | 8 ++ 3 files changed, 144 insertions(+) create mode 100644 challenges/2023/03-gearRatios/README.md create mode 100644 challenges/2023/03-gearRatios/main.py create mode 100644 challenges/2023/03-gearRatios/tests.json diff --git a/challenges/2023/03-gearRatios/README.md b/challenges/2023/03-gearRatios/README.md new file mode 100644 index 0000000..46c8392 --- /dev/null +++ b/challenges/2023/03-gearRatios/README.md @@ -0,0 +1 @@ +# [Day 3: Gear Ratios](https://adventofcode.com/2023/day/3) diff --git a/challenges/2023/03-gearRatios/main.py b/challenges/2023/03-gearRatios/main.py new file mode 100644 index 0000000..a84ac53 --- /dev/null +++ b/challenges/2023/03-gearRatios/main.py @@ -0,0 +1,135 @@ +import os +import sys + + +def _debug(*args, **kwargs): + kwargs["file"] = sys.stderr + print(*args, **kwargs) + + +Coordinate = tuple[int, int] +Schematic = dict[Coordinate, str] + + +def parse(instr: str) -> Schematic: + res = {} + + lines = instr.splitlines() + max_x = len(lines[0]) + + for row_n, row in enumerate(lines): + assert len(row) == max_x + for col_n, char in enumerate(row): + res[(col_n, row_n)] = char + + return res + + +DIRECTIONS = [(-1, -1), (0, -1), (1, -1), (-1, 0), (1, 0), (-1, 1), (0, 1), (1, 1)] + + +def apply_coord_delta(c: Coordinate, d: Coordinate) -> Coordinate: + a, b = c + e, f = d + return a + e, b + f + + +def seek_digits( + sc: Schematic, start: Coordinate, delta: Coordinate +) -> tuple[str, set[Coordinate]]: + digits = "" + coords = set() + + cursor = start + while True: + cursor = apply_coord_delta(cursor, delta) + val = sc.get(cursor, ".") + if not val.isdigit(): + break + coords.add(cursor) + digits += val + + return digits, coords + + +def collect_digits_around( + sc: Schematic, start: Coordinate +) -> tuple[int, set[Coordinate]]: + backward_digits, backward_coords = seek_digits(sc, start, (-1, 0)) + forward_digits, forward_coords = seek_digits(sc, start, (1, 0)) + + return ( + int("".join(reversed(backward_digits)) + sc[start] + forward_digits), + backward_coords | forward_coords | set((start,)), + ) + + +def one(inp: str): + schematic = parse(inp) + + consumed_numbers = set() + acc = 0 + + for coord in schematic: + if coord in consumed_numbers: + continue + + char = schematic[coord] + + if not char.isdigit(): + continue + + is_part_number = False + for delta in DIRECTIONS: + target = schematic.get(apply_coord_delta(coord, delta), ".") + if not (target.isdigit() or target == "."): + is_part_number = True + break + + if is_part_number: + n, used_coords = collect_digits_around(schematic, coord) + consumed_numbers = consumed_numbers | used_coords + acc += int(n) + + return acc + + +def two(inp: str): + schematic = parse(inp) + acc = 0 + + for coord in schematic: + char = schematic[coord] + + if char != "*": + continue + + consumed_numbers = set() + numbers = [] + + for delta in DIRECTIONS: + test_coord = apply_coord_delta(coord, delta) + if test_coord in consumed_numbers: + continue + if schematic.get(test_coord, ".").isdigit(): + n, c = collect_digits_around(schematic, test_coord) + consumed_numbers = consumed_numbers | c + numbers.append(n) + + if len(numbers) == 2: + # is gear! + x, y = numbers + acc += x * y + + return acc + + +if __name__ == "__main__": + if len(sys.argv) < 2 or sys.argv[1] not in ["1", "2"]: + print("Missing day argument", file=sys.stderr) + os.exit(1) + inp = sys.stdin.read().strip() + if sys.argv[1] == "1": + print(one(inp)) + else: + print(two(inp)) diff --git a/challenges/2023/03-gearRatios/tests.json b/challenges/2023/03-gearRatios/tests.json new file mode 100644 index 0000000..bc5518a --- /dev/null +++ b/challenges/2023/03-gearRatios/tests.json @@ -0,0 +1,8 @@ +{ + "1": [ + {"res": "4361", "in": "467..114..\n...*......\n..35..633.\n......#...\n617*......\n.....+.58.\n..592.....\n......755.\n...$.*....\n.664.598.."} + ], + "2": [ + {"res": "467835", "in": "467..114..\n...*......\n..35..633.\n......#...\n617*......\n.....+.58.\n..592.....\n......755.\n...$.*....\n.664.598.."} + ] +}