static void tryAddNode(CaveNode next) { if (closedNodes.Contains(next)) { return; } CaveNode candidate; if (openNodes.Contains(next)) //update f and g as necessary { openNodes.TryGetValue(next, out candidate); candidate.costToNode = Math.Min(candidate.costToNode, next.costToNode); candidate.f = Math.Min(candidate.f, next.f); } else { openNodes.Add(next); } }
public static void Run() { Console.WriteLine("\nDay 22"); int[][] erosionGrid; int[][] terrainGrid; int targetX; int targetY; int depth; using (StreamReader reader = new StreamReader("input/input22.txt")) { depth = int.Parse(reader.ReadLine().Split(' ')[1]); string[] target = reader.ReadLine().Split(' ', ','); targetX = int.Parse(target[1]); targetY = int.Parse(target[2]); erosionGrid = new int[(targetY + 100)][]; terrainGrid = new int[(targetY + 100)][]; for (int row = 0; row < erosionGrid.Length; row++) { erosionGrid[row] = new int[targetX + 100]; terrainGrid[row] = new int[targetX + 100]; } } for (int y = 0; y < erosionGrid.Length; y++) { for (int x = 0; x < erosionGrid[y].Length; x++) { if (targetX == x && targetY == y) { erosionGrid[y][x] = depth % 20183; } else if (x == 0) { if (y == 0) { erosionGrid[y][x] = depth % 20183; } else { erosionGrid[y][x] = (y * 48271 + depth) % 20183; } } else if (y == 0) { erosionGrid[y][x] = (x * 16807 + depth) % 20183; } else { erosionGrid[y][x] = (erosionGrid[y - 1][x] * erosionGrid[y][x - 1] + depth) % 20183; } terrainGrid[y][x] = erosionGrid[y][x] % 3; } } Console.WriteLine("Total Risk Level: " + (terrainGrid.Take(targetY + 1).Sum(x => x.Take(targetX + 1).Sum()))); openNodes.Add(new CaveNode(null, 0, 0, targetX, targetY, 0, 0)); //start with torch while (true) { CaveNode currNode = openNodes.FirstOrDefault(); if (currNode.x == targetX && currNode.y == targetY) { if (currNode.equipment == 0) { Console.WriteLine("Quickest Time to Target: " + currNode.costToNode); break; } else //switch to torch and check other candidates for faster pathing that arrive with the torch already equipped { currNode.equipment = 0; currNode.f += 7; } } else { closedNodes.Add(currNode); openNodes.Remove(currNode); int terrain; if (currNode.x > 0) //check if array index is in bounds, then continue with current equipment if possible, else switch to proper equipment { terrain = terrainGrid[currNode.y][currNode.x - 1]; if (currNode.equipment != (terrain + 2) % 3) { tryAddNode(new CaveNode(currNode, currNode.x - 1, currNode.y, targetX, targetY, terrain, currNode.equipment)); } else { tryAddNode(new CaveNode(currNode, currNode.x - 1, currNode.y, targetX, targetY, terrain, (3 + terrain - currNode.terrain + currNode.equipment) % 3)); } } if (currNode.y > 0) { terrain = terrainGrid[currNode.y - 1][currNode.x]; if (currNode.equipment != (terrain + 2) % 3) { tryAddNode(new CaveNode(currNode, currNode.x, currNode.y - 1, targetX, targetY, terrain, currNode.equipment)); } else { tryAddNode(new CaveNode(currNode, currNode.x, currNode.y - 1, targetX, targetY, terrain, (3 + terrain - currNode.terrain + currNode.equipment) % 3)); } } if (currNode.y < terrainGrid.Length - 1) { terrain = terrainGrid[currNode.y + 1][currNode.x]; if (currNode.equipment != (terrain + 2) % 3) { tryAddNode(new CaveNode(currNode, currNode.x, currNode.y + 1, targetX, targetY, terrain, currNode.equipment)); } else { tryAddNode(new CaveNode(currNode, currNode.x, currNode.y + 1, targetX, targetY, terrain, (3 + terrain - currNode.terrain + currNode.equipment) % 3)); } } if (currNode.x < terrainGrid[currNode.y].Length - 1) { terrain = terrainGrid[currNode.y][currNode.x + 1]; if (currNode.equipment != (terrain + 2) % 3) { tryAddNode(new CaveNode(currNode, currNode.x + 1, currNode.y, targetX, targetY, terrain, currNode.equipment)); } else { tryAddNode(new CaveNode(currNode, currNode.x + 1, currNode.y, targetX, targetY, terrain, (3 + terrain - currNode.terrain + currNode.equipment) % 3)); } } } } }