diff --git a/challenges/2024/06-guardGallivant/README.md b/challenges/2024/06-guardGallivant/README.md new file mode 100644 index 0000000..9bf820e --- /dev/null +++ b/challenges/2024/06-guardGallivant/README.md @@ -0,0 +1,5 @@ +# [Day 6: Guard Gallivant](https://adventofcode.com/2024/day/6) + +Part 2 is: +* higher than 456 +* less than 1689 \ No newline at end of file diff --git a/challenges/2024/06-guardGallivant/main.py b/challenges/2024/06-guardGallivant/main.py new file mode 100644 index 0000000..72c3967 --- /dev/null +++ b/challenges/2024/06-guardGallivant/main.py @@ -0,0 +1,84 @@ +import sys +from gridutil import grid, coord +from typing import Optional +from tqdm import tqdm + + +def parse(instr: str) -> grid.Grid: + return grid.parse(instr) + + +def find_start(g: grid.Grid) -> coord.Coordinate: + for pos in g: + if g[pos] == "^": + return pos + assert False, "no start point found" + + +def modplus(x: int) -> int: + return (x + 1) % 4 + + +dirs = [coord.Direction.Up, coord.Direction.Right, coord.Direction.Down, coord.Direction.Left] + + +class LoopEncounteredException(Exception): + pass + + +def trace(g: grid.Grid, guard_pos: coord.Coordinate, guard_direction: int) -> set[tuple[coord.Coordinate, int]]: + visited_sequence = set() + + while guard_pos in g: + if (guard_pos, guard_direction) in visited_sequence: + raise LoopEncounteredException + + visited_sequence.add((guard_pos, guard_direction)) + + nc = coord.add(guard_pos, dirs[guard_direction % 4].delta()) + if nc in g and g[nc] == "#": + guard_direction = modplus(guard_direction) + else: + guard_pos = nc + + return visited_sequence + + +def one(instr: str) -> int: + g = parse(instr) + return len(set(map(lambda x: x[0], trace(g, find_start(g), 0)))) + + +def two(instr: str) -> int: + g = parse(instr) + + start_pos = find_start(g) + seq = trace(g, start_pos, 0) + known_blocks = set() + + for (pos, _) in tqdm(seq, file=sys.stderr): + assert pos in g, "pos off the rails" + g[pos] = "#" + try: + trace(g, start_pos, 0) + except LoopEncounteredException: + known_blocks.add(pos) + g[pos] = "." + + return len(known_blocks) + + +def _debug(*args, **kwargs): + kwargs["file"] = sys.stderr + print(*args, **kwargs) + + +if __name__ == "__main__": + if len(sys.argv) < 2 or sys.argv[1] not in ["1", "2"]: + print("Missing day argument", file=sys.stderr) + sys.exit(1) + inp = sys.stdin.read().strip() + if sys.argv[1] == "1": + print(one(inp)) + else: + print(two(inp)) \ No newline at end of file diff --git a/challenges/2024/06-guardGallivant/sample.txt b/challenges/2024/06-guardGallivant/sample.txt new file mode 100644 index 0000000..a4eb402 --- /dev/null +++ b/challenges/2024/06-guardGallivant/sample.txt @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#..^..... +........#. +#......... +......#... diff --git a/challenges/2024/06-guardGallivant/tests.json b/challenges/2024/06-guardGallivant/tests.json new file mode 100644 index 0000000..a9d142e --- /dev/null +++ b/challenges/2024/06-guardGallivant/tests.json @@ -0,0 +1,14 @@ +{ + "1": [ + { + "is": "41", + "input": "....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...\n\n" + } + ], + "2": [ + { + "is": "6", + "input": "....#.....\n.........#\n..........\n..#.......\n.......#..\n..........\n.#..^.....\n........#.\n#.........\n......#...\n" + } + ] +} \ No newline at end of file diff --git a/challenges/2024/README.md b/challenges/2024/README.md index f9cfb0c..b3d569c 100644 --- a/challenges/2024/README.md +++ b/challenges/2024/README.md @@ -4,7 +4,7 @@ Solutions to the [2024 Advent of Code](https://adventofcode.com/2024)! --- -Total stars: **10 ★** +Total stars: **12 ★** ![Benchmark graph](./benchmark-graph.png) @@ -18,4 +18,5 @@ A day denoted with an asterisk means it has a visualisation. | 02 - Red-Nosed Reindeer | ★ ★ | Python || | 03 - Mull It Over | ★ ★ | Python | The first instance of Advent of Parsing this year! | | 04* - Ceres Search | ★ ★ | Python | When it says a cross, it does not mean a plus. | -| 05 - Print Queue | ★ ★ | Python | Before you dismiss and idea as being "too simple", make sure you check that it doesn't work. | \ No newline at end of file +| 05 - Print Queue | ★ ★ | Python | Before you dismiss and idea as being "too simple", make sure you check that it doesn't work. | +| 06 - Guard Gallivant | ★ ★ | Python | oh dear runtime (also I knew what I wanted to do for so long it just took me 3 hours to implement it properly) | \ No newline at end of file diff --git a/challenges/2024/benchmark-graph.png b/challenges/2024/benchmark-graph.png index 0c95cb0..cf7293b 100644 Binary files a/challenges/2024/benchmark-graph.png and b/challenges/2024/benchmark-graph.png differ diff --git a/challenges/2024/benchmarks.jsonl b/challenges/2024/benchmarks.jsonl index 43d0c75..2b38f29 100644 --- a/challenges/2024/benchmarks.jsonl +++ b/challenges/2024/benchmarks.jsonl @@ -8,3 +8,5 @@ {"day": 4, "part": 2, "runner": "py", "min": 0.05280470848083496, "max": 0.06299543380737305, "avg": 0.05627016305923462, "n": 100} {"day": 5, "part": 1, "runner": "py", "min": 0.02001357078552246, "max": 0.030559301376342773, "avg": 0.02152919292449951, "n": 100} {"day": 5, "part": 2, "runner": "py", "min": 0.02507805824279785, "max": 0.03197765350341797, "avg": 0.027084295749664308, "n": 100} +{"day": 6, "part": 1, "runner": "py", "min": 0.0671079158782959, "max": 0.0671079158782959, "avg": 0.0671079158782959, "n": 1} +{"day": 6, "part": 2, "runner": "py", "min": 61.63975167274475, "max": 61.63975167274475, "avg": 61.63975167274475, "n": 1}