#define Day15 using System.Collections.Generic; using System.Diagnostics; using AoC2021; #if Day15 var lines = File.ReadAllLines("day15/input"); var cave = new int[lines.Length, lines[0].Length]; lines.ForEachIndex((l, row) => l.ForEachIndex((c, col)=> cave[row, col] = int.Parse(c.ToString()))); Console.WriteLine(Check(cave)); int rowLength = cave.GetLength(0); int colLength = cave.GetLength(1); var largerCave = new int[lines.Length*5, lines[0].Length*5]; for (int timeRow = 0; timeRow < 5; timeRow++) { for (int timesCol = 0; timesCol < 5; timesCol++) { for (int row = 0; row < rowLength; row++) { for (int col = 0; col < colLength; col++) { largerCave[rowLength * timeRow + row, colLength*timesCol + col] = ((cave[row, col] + timeRow + timesCol - 1) % 9) + 1; } } } } Console.WriteLine(Check(largerCave)); long Check(int[,] caveToCheck) { var pos = new Point(0, 0); var end = new Point(caveToCheck.GetLength(0) - 1, caveToCheck.GetLength(1) - 1); var visitedLowest = new Dictionary() { { pos, 0 } }; long min = 0; var sortedListReplacement = new Dictionary>() { { 0, new List() { new PointWithVisited(pos, new HashSet()) } } }; while (true) { if (!sortedListReplacement.ContainsKey(min)) { min++; continue; } var minPoints = sortedListReplacement[min]; if (minPoints.Count <= 0) { min++; continue; } var cur = minPoints.First(); if (cur.point.Equals(end)) { return min; } minPoints.Remove(cur); var adjacent = GetAdjacent(cur.point, cur.visited, caveToCheck); foreach (var a in adjacent) { var riskLevel = min + caveToCheck[a.row, a.col]; if (visitedLowest.ContainsKey(a) && visitedLowest[a] <= riskLevel) { continue; } visitedLowest[a] = riskLevel; AddToCheck(a, riskLevel, cur, sortedListReplacement); } } } void AddToCheck(Point p, long sum, PointWithVisited previous, Dictionary> sortedListReplacement) { var copy = previous.visited.ToHashSet(); copy.Add(previous.point); if (!sortedListReplacement.ContainsKey(sum)) { sortedListReplacement.Add(sum, new List() {new PointWithVisited(p, copy)}); return; } sortedListReplacement[sum].Add(new PointWithVisited(p, copy)); } List GetAdjacent(Point cur, HashSet visited, int[,] caveToCheck) { return new List() { new Point(cur.row + 1, cur.col), new Point(cur.row - 1, cur.col), new Point(cur.row, cur.col + 1), new Point(cur.row, cur.col - 1), }.Where(p => p.row >= 0 && p.row < caveToCheck.GetLength(0) && p.col >= 0 && p.col < caveToCheck.GetLength(1)) .Where(p => !visited.Contains(p)) .ToList(); } record PointWithVisited(Point point, HashSet visited); record Point(int row, int col); #endif