Day 15: Replace sortedListReplacement with PriorityQueue

Use ImmutableHashSet instead of HashSet so visited points do not have to
 be copied
Format code
This commit is contained in:
Stefan Forstenlechner 2021-12-15 23:16:18 +01:00
parent 3be5aca277
commit ee2d1f4bda
1 changed files with 18 additions and 38 deletions

View File

@ -1,23 +1,23 @@
#define Day15
using System.Collections.Generic;
#if Day15
using System.Collections.Immutable;
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())));
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];
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;
largerCave[rowLength * timeRow + row, colLength * timesCol + col] = ((cave[row, col] + timeRow + timesCol - 1) % 9) + 1;
}
}
}
@ -29,60 +29,40 @@ 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<Point, long>() { { pos, 0 } };
long min = 0;
var sortedListReplacement = new Dictionary<long, List<PointWithVisited>>() { { 0, new List<PointWithVisited>() { new PointWithVisited(pos, new HashSet<Point>()) } } };
var minPaths = new PriorityQueue<PointWithVisited, long>();
minPaths.Enqueue(new PointWithVisited(pos, ImmutableHashSet.Create<Point>()), 0);
while (true) {
if (!sortedListReplacement.ContainsKey(min)) {
min++;
continue;
}
var minPoints = sortedListReplacement[min];
if (minPoints.Count <= 0) {
min++;
continue;
}
var cur = minPoints.First();
minPaths.TryDequeue(out PointWithVisited cur, out long min);
if (cur.point.Equals(end)) {
return min;
}
minPoints.Remove(cur);
var adjacent = GetAdjacent(cur.point, cur.visited, caveToCheck);
var nextVisited = cur.visited.Add(cur.point);
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);
minPaths.Enqueue(new PointWithVisited(a, nextVisited), riskLevel);
}
}
}
void AddToCheck(Point p, long sum, PointWithVisited previous, Dictionary<long, List<PointWithVisited>> sortedListReplacement) {
var copy = previous.visited.ToHashSet();
copy.Add(previous.point);
if (!sortedListReplacement.ContainsKey(sum)) {
sortedListReplacement.Add(sum, new List<PointWithVisited>() {new PointWithVisited(p, copy)});
return;
}
sortedListReplacement[sum].Add(new PointWithVisited(p, copy));
}
List<Point> GetAdjacent(Point cur, HashSet<Point> visited, int[,] caveToCheck) {
List<Point> GetAdjacent(Point cur, ImmutableHashSet<Point> visited, int[,] caveToCheck) {
return new List<Point>() {
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))
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<Point> visited);
record PointWithVisited(Point point, ImmutableHashSet<Point> visited);
record Point(int row, int col);
#endif