private static void MainDay22() { var risk = 0; for (var xIndex = 0; xIndex <= targetX; xIndex++) { for (var yIndex = 0; yIndex <= targetY; yIndex++) { risk += ErosionLevel(xIndex, yIndex) % 3; } } Console.WriteLine($"Risk level : {risk}"); var visitedRooms = new Dictionary <Coord, int>(); var done = new HashSet <Coord>(); var start = new Coord(0, 0, Equipment.Torch); minDistToTarget = start.ManhattanDistance(new Coord(targetX, targetY, Equipment.Torch)) * 8; for (visitedRooms.Add(start, 0);;) { var minDist = int.MaxValue; Coord closestRoom = null; foreach (var pair in visitedRooms) { if (pair.Value < minDist) { minDist = pair.Value; closestRoom = pair.Key; } } visitedRooms.Remove(closestRoom); done.Add(closestRoom); if (minDist > minDistToTarget) { // we have found the shortest possible path break; } // examine rooms around if (closestRoom.X > 0) { DistToNeighbout(closestRoom, closestRoom.X - 1, closestRoom.Y, minDist, visitedRooms, done); } DistToNeighbout(closestRoom, closestRoom.X + 1, closestRoom.Y, minDist, visitedRooms, done); if (closestRoom.Y > 0) { DistToNeighbout(closestRoom, closestRoom.X, closestRoom.Y - 1, minDist, visitedRooms, done); } DistToNeighbout(closestRoom, closestRoom.X, closestRoom.Y + 1, minDist, visitedRooms, done); // stay in place, but change gear UpdateDistToRoom(closestRoom.ChangeEquipment(), minDist + 7, visitedRooms, done); } Console.WriteLine($"Shortest path: {minDistToTarget}"); }