From 73a1b0567a9fd50e863605f125de40b4b48a0f89 Mon Sep 17 00:00:00 2001 From: Parnic Date: Fri, 20 Dec 2024 17:37:58 -0600 Subject: [PATCH] Day 20 This is slower than I'd like but I'm kinda tired of grids, so...probably not going to revisit it to improve. --- src/20.cs | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 src/20.cs diff --git a/src/20.cs b/src/20.cs new file mode 100644 index 0000000..0173cb5 --- /dev/null +++ b/src/20.cs @@ -0,0 +1,133 @@ +using aoc2024.Util; + +namespace aoc2024; + +internal class Day20 : Day +{ + private ivec2 startPos = ivec2.ZERO; + private ivec2 endPos = ivec2.ZERO; + private bool[,] grid = new bool[1,1]; + internal override void Parse() + { + var lines = Util.Parsing.ReadAllLines($"{GetDay()}").ToList(); + grid = new bool[lines.Count, lines[0].Length]; + for (var y = 0; y < lines.Count; y++) + { + for (var x = 0; x < lines[y].Length; x++) + { + if (lines[y][x] == '#') + { + grid[y, x] = true; + } + else if (lines[y][x] == 'S') + { + startPos = new ivec2(x, y); + } + else if (lines[y][x] == 'E') + { + endPos = new ivec2(x, y); + } + } + } + } + + internal override string Part1() + { + Dictionary distances = []; + distances[endPos] = 0; + Queue q = []; + q.Enqueue(endPos); + while (q.TryDequeue(out var pos)) + { + foreach (var neighbor in pos.GetBoundedOrthogonalNeighbors(0, 0, grid.GetLength(0) - 1, + grid.GetLength(1) - 1)) + { + if (!grid[neighbor.y, neighbor.x] && (!distances.TryGetValue(neighbor, out var distance) || distance > distances[pos] + 1)) + { + if (neighbor != startPos) + { + q.Enqueue(neighbor); + } + + distances.Add(neighbor, distances[pos] + 1); + } + } + } + + var shortcuts = new Dictionary(); + foreach (var src in distances) + { + foreach (var target in distances) + { + if (src.Key.ManhattanDistanceTo(target.Key) != 2) + { + continue; + } + + var distSaved = src.Value - target.Value - 2; + if (distSaved <= 0) + { + continue; + } + if (!shortcuts.TryAdd(distSaved, 1)) + { + shortcuts[distSaved]++; + } + } + } + + long numSavingAtLeast100 = shortcuts.Where(s => s.Key >= 100).Sum(s => s.Value); + return $"2-cell skips saving 100+ picoseconds: <+white>{numSavingAtLeast100}"; + } + + internal override string Part2() + { + Dictionary distances = []; + distances[endPos] = 0; + Queue q = []; + q.Enqueue(endPos); + while (q.TryDequeue(out var pos)) + { + foreach (var neighbor in pos.GetBoundedOrthogonalNeighbors(0, 0, grid.GetLength(0) - 1, + grid.GetLength(1) - 1)) + { + if (!grid[neighbor.y, neighbor.x] && (!distances.TryGetValue(neighbor, out var distance) || distance > distances[pos] + 1)) + { + if (neighbor != startPos) + { + q.Enqueue(neighbor); + } + + distances.Add(neighbor, distances[pos] + 1); + } + } + } + + var shortcuts = new Dictionary(); + foreach (var src in distances) + { + foreach (var target in distances) + { + var distTo = src.Key.ManhattanDistanceTo(target.Key); + if (distTo is 0 or > 20) + { + continue; + } + + var distSaved = src.Value - target.Value - distTo; + if (distSaved <= 0) + { + continue; + } + + if (!shortcuts.TryAdd(distSaved, 1)) + { + shortcuts[distSaved]++; + } + } + } + + long numSavingAtLeast100 = shortcuts.Where(s => s.Key >= 100).Sum(s => s.Value); + return $"0-20-cell skips saving 100+ picoseconds: <+white>{numSavingAtLeast100}"; + } +}