diff --git a/src/06.cs b/src/06.cs new file mode 100644 index 0000000..3d8c0eb --- /dev/null +++ b/src/06.cs @@ -0,0 +1,102 @@ +using aoc2024.Util; + +namespace aoc2024; + +internal class Day06 : Day +{ + private bool[][] grid = []; + private ivec2 startPos; + private ivec2 startDir; + internal override void Parse() + { + var lines = Util.Parsing.ReadAllLines($"{GetDay()}").ToList(); + grid = new bool[lines.Count][]; + for (int i = 0; i < lines.Count; i++) + { + var line = lines[i]; + var row = new bool[line.Length]; + for (int j = 0; j < line.Length; j++) + { + if (line[j] == '#') + { + row[j] = true; + } + else + { + row[j] = false; + if (line[j] != '.') + { + startPos = new ivec2(j, i); + startDir = ivec2.DirFromChar(line[j]); + } + } + } + + grid[i] = row; + } + } + + private (bool, HashSet) HasLoop() + { + var currPos = startPos; + var currDir = startDir; + var loopSet = new HashSet<(ivec2, ivec2)>(10000); + var visited = new HashSet(10000); + while (true) + { + visited.Add(currPos); + if (!loopSet.Add((currPos, currDir))) + { + return (true, visited); + } + + var nextPos = currPos + currDir; + if (!nextPos.IsWithinRange(0, 0, grid[0].Length - 1, grid.Length - 1)) + { + return (false, visited); + } + + if (grid[nextPos.y][nextPos.x]) + { + currDir = currDir.GetRotatedRight(); + } + else + { + currPos += currDir; + } + } + } + + internal override string Part1() + { + var (_, visited) = HasLoop(); + return $"Locations visited: <+white>{visited.Count}"; + } + + internal override string Part2() + { + var (_, allVisited) = HasLoop(); + + int numBlockedLoops = 0; + foreach (var pos in allVisited) + { + var (x, y) = (pos.x, pos.y); + if (startPos == pos) + { + continue; + } + + grid[y][x] = true; + + var (hasLoop, _) = HasLoop(); + if (hasLoop) + { + numBlockedLoops++; + } + + grid[y][x] = false; + } + + return $"# obstructions that cause a loop: <+white>{numBlockedLoops}"; + } +} diff --git a/src/Util/Vec2.cs b/src/Util/Vec2.cs index 4e56014..73f955d 100644 --- a/src/Util/Vec2.cs +++ b/src/Util/Vec2.cs @@ -38,6 +38,15 @@ public readonly struct ivec2 : IEquatable, IComparable, IComparabl public long ManhattanDistance => Abs(this).Sum; public long ManhattanDistanceTo(ivec2 other) => System.Math.Abs(x - other.x) + System.Math.Abs(y - other.y); + public static ivec2 DirFromChar(char ch) => ch switch + { + '^' => UP, + '>' => RIGHT, + '<' => LEFT, + 'v' => DOWN, + _ => throw new FormatException($"Invalid direction {ch}"), + }; + public ivec2 GetBestDirectionTo(ivec2 p) { ivec2 diff = p - this;