using System.Collections.Immutable; namespace _2021___Day_15 { record Point(int x, int y); class Program { static void Main() { string inp = File.ReadAllText(@"../../../../Input.in"); var map = inp.Split("\n"); var chitonMap = new Dictionary<Point, int>( from y in Enumerable.Range(0, map.Length) from x in Enumerable.Range(0, map[0].Length - 1) select new KeyValuePair<Point, int>(new Point(x, y), map[y][x] - '0') ); Console.WriteLine(FindPath(chitonMap)); Console.WriteLine(FindPath(MakeBig(chitonMap))); } static int FindPath(Dictionary<Point, int> map) { var topLeft = new Point(0, 0); var bottomRight = new Point(map.Keys.MaxBy(p => p.x).x, map.Keys.MaxBy(p => p.y).y); var q = new PriorityQueue<Point, int>(); var totalRiskMap = new Dictionary<Point, int>(); totalRiskMap[topLeft] = 0; q.Enqueue(topLeft, 0); while (true) { var p = q.Dequeue(); if (p == bottomRight) { break; } foreach (var n in Neighbors(p)) { if (map.ContainsKey(n)) { var totalRiskWhen = totalRiskMap[p] + map[n]; if (totalRiskWhen < totalRiskMap.GetValueOrDefault(n, int.MaxValue)) { totalRiskMap[n] = totalRiskWhen; q.Enqueue(n, totalRiskWhen); } } } } return totalRiskMap[bottomRight]; } static Dictionary<Point, int> MakeBig(Dictionary<Point, int> map) { var (ccol, crow) = (map.Keys.MaxBy(p => p.x).x + 1, map.Keys.MaxBy(p => p.y).y + 1); var res = new Dictionary<Point, int>( from y in Enumerable.Range(0, crow * 5) from x in Enumerable.Range(0, ccol * 5) let tileY = y % crow let tileX = x % ccol let tileRiskLevel = map[new Point(tileX, tileY)] let tileDistance = (y / crow) + (x / ccol) let riskLevel = (tileRiskLevel + tileDistance - 1) % 9 + 1 select new KeyValuePair<Point, int>(new Point(x, y), riskLevel) ); return res; } static IEnumerable<Point> Neighbors(Point point) => new[] { point with {y = point.y + 1}, point with {y = point.y - 1}, point with {x = point.x + 1}, point with {x = point.x - 1}, }; } }