diff --git a/Solutions/2024/Day18.cs b/Solutions/2024/Day18.cs index 653d905..4a557d4 100644 --- a/Solutions/2024/Day18.cs +++ b/Solutions/2024/Day18.cs @@ -19,47 +19,45 @@ public static void Init(string[] input, Action? visualise = null public static int Part1(string[] _, params object[]? args) { - int gridSize = args.GridSize(); - int noOfBytes = args.Bytes(); + int size = args.MemorySpaceSize(); + int noOfBytes = args.NoOfBytes(); Point start = Point.Zero; - Point end = new(gridSize - 1, gridSize - 1); + Point end = new(size - 1, size - 1); - _bytes.Take(noOfBytes).VisualiseRam("Initial state:", gridSize, []); + _bytes.Take(noOfBytes).VisualiseRam("Initial state:", size, []); - List shortestPath = FindShortestPath(start, end, _bytes.Take(noOfBytes), gridSize); + List shortestPath = FindShortestPath(start, end, _bytes.Take(noOfBytes), size); - _bytes.Take(noOfBytes).VisualiseRam("Final:", gridSize, shortestPath); + _bytes.Take(noOfBytes).VisualiseRam("Final:", size, shortestPath); return shortestPath.Count - 1; // shortestPath includes start } public static string Part2(string[] _, params object[]? args) { - int gridSize = args.GridSize(); - int noOfBytes = args.Bytes(); + int size = args.MemorySpaceSize(); + int noOfBytes = _bytes.Count; Point start = Point.Zero; - Point end = new(gridSize - 1, gridSize - 1); + Point end = new(size - 1, size - 1); - List shortestPath = [Point.Zero]; - while (shortestPath is not []) { - shortestPath = FindShortestPath(start, end, _bytes.Take(++noOfBytes), gridSize); + List shortestPath = []; + while (shortestPath is []) { + shortestPath = FindShortestPath(start, end, _bytes.Take(--noOfBytes), size); } - noOfBytes--; return $"{_bytes[noOfBytes].X},{_bytes[noOfBytes].Y}"; } - public static List FindShortestPath(Point start, Point goal, IEnumerable obstacles, int gridSize) + public static List FindShortestPath(Point start, Point goal, IEnumerable bytes, int size) { - PriorityQueue priorityQueue = new(); - Dictionary cost = new() { [start] = 0 }; - Dictionary distances = new() { [start] = start.ManhattanDistance(goal) }; - Dictionary previous = []; - - HashSet obstaclesSet = [.. obstacles]; + Dictionary cost = new() { [start] = 0 }; + Dictionary distances = new() { [start] = start.ManhattanDistance(goal) }; + Dictionary previous = []; + HashSet corruptions = [.. bytes]; + PriorityQueue priorityQueue = new(); priorityQueue.Enqueue(start, distances[start]); while (priorityQueue.Count > 0) { @@ -72,20 +70,16 @@ public static List FindShortestPath(Point start, Point goal, IEnumerable< foreach (Direction direction in Directions.NSEW) { Point adjacent = current + direction.Delta(); - // Ignore invalid neighbours - if (adjacent.X < 0 || adjacent.Y < 0 || adjacent.X >= gridSize || adjacent.Y >= gridSize - || obstaclesSet.Contains(adjacent)) { + if (adjacent.IsOutOfBounds(size) || corruptions.Contains(adjacent)) { continue; } int tentativeCost = cost[current] + 1; if (tentativeCost < cost.GetValueOrDefault(adjacent, int.MaxValue)) { - previous[adjacent] = current; - cost[adjacent] = tentativeCost; + previous[adjacent] = current; + cost[adjacent] = tentativeCost; distances[adjacent] = tentativeCost + adjacent.ManhattanDistance(goal); - - // Add to priority queue with updated distance score priorityQueue.Enqueue(adjacent, distances[adjacent]); } } @@ -94,20 +88,24 @@ public static List FindShortestPath(Point start, Point goal, IEnumerable< return []; // No path found } - private static List ReconstructPath(Dictionary cameFrom, Point current) + private static bool IsOutOfBounds(this Point adjacent, int gridSize) + => adjacent.X < 0 || adjacent.X >= gridSize + || adjacent.Y < 0 || adjacent.Y >= gridSize; + + private static List ReconstructPath(Dictionary previous, Point current) { - List totalPath = [current]; + List fullPath = [current]; - while (cameFrom.ContainsKey(current)) { - current = cameFrom[current]; - totalPath.Insert(0, current); + while (previous.ContainsKey(current)) { + current = previous[current]; + fullPath = [current, .. fullPath]; } - return totalPath; + return fullPath; } - private static int GridSize(this object[]? args) => GetArgument(args, 1, 71); - private static int Bytes(this object[]? args) => GetArgument(args, 2, 1024); + private static int MemorySpaceSize(this object[]? args) => GetArgument(args, 1, 71); + private static int NoOfBytes(this object[]? args) => GetArgument(args, 2, 1024); private static void VisualiseRam(this IEnumerable bytes, string title, int gridSize, IEnumerable route, bool clearScreen = false) {