More day 12 optimizations

Down to  ~98ms from the original ~940ms. That's a very respectable gain, but I am still not quite happy with the runtime. At this point, though, I think I will need to re-think my approach rather than making small tweaks.
This commit is contained in:
2021-12-12 11:25:58 -06:00
parent c292bd45c6
commit 5c37fc4129

View File

@ -11,6 +11,15 @@ internal class Day12
foreach (var line in lines)
{
var points = line.Split('-');
if (points[0] == "start" || points[0] == "end")
{
points[0] = points[0].ToUpper();
}
if (points[1] == "start" || points[1] == "end")
{
points[1] = points[1].ToUpper();
}
if (!paths.ContainsKey(points[0]))
{
paths[points[0]] = new List<string>();
@ -20,11 +29,11 @@ internal class Day12
paths[points[1]] = new List<string>();
}
if (points[0] != "end" && points[1] != "start")
if (points[0] != "END" && points[1] != "START")
{
paths[points[0]].Add(points[1]);
}
if (points[1] != "end" && points[0] != "start")
if (points[1] != "END" && points[0] != "START")
{
paths[points[1]].Add(points[0]);
}
@ -39,35 +48,35 @@ internal class Day12
using var t = new Timer();
var validPaths = new List<List<string>>();
FindPaths(paths, validPaths, new List<string>(){ "start" }, false);
FindPaths(paths, validPaths, new List<string>(){ "START" }, false);
Logger.Log($"part1: {validPaths.Count}");
//validPaths.ForEach(path => Logger.Log($" {string.Join(',', path)}"));
}
private static void FindPaths(Dictionary<string, List<string>> paths, List<List<string>> routes, List<string> currRoute, bool canVisitSmallCaveTwice, bool hasDoubledCave = false)
{
//Logger.Log($"Current path: {string.Join(',', currRoute)}");
var curr = currRoute.Last();
bool justDoubled = false;
foreach (var next in paths[curr])
{
//Logger.Log($" Evaluating next: {next}");
if (next != "end" && next.ToLower() == next && currRoute.Contains(next))
if (IsSmallCave(next) && currRoute.Contains(next))
{
if (!canVisitSmallCaveTwice || hasDoubledCave)
{
//Logger.Log($" is already-visited small cave, skipping");
continue;
}
else if (currRoute.Any(x => x[0] >= 'a' && x[0] <= 'z' && currRoute.Count(y => x == y) == 2))
{
//Logger.Log($" is already-visited small cave and we have already been to another one twice, skipping");
hasDoubledCave = true;
continue;
}
hasDoubledCave = true;
justDoubled = true;
}
//Logger.Log($" adding to route");
currRoute.Add(next);
if (next == "end")
if (next == "END")
{
//Logger.Log($" is end, so adding {string.Join(',', currRoute)} to valid paths");
routes.Add(new List<string>(currRoute));
@ -78,18 +87,25 @@ internal class Day12
}
currRoute.RemoveAt(currRoute.Count - 1);
if (justDoubled)
{
hasDoubledCave = false;
}
}
//Logger.Log(" done with route");
}
private static bool IsSmallCave(string cave) => cave[0] >= 'a' && cave[0] <= 'z';
private static void Part2(Dictionary<string, List<string>> paths)
{
using var t = new Timer();
var validPaths = new List<List<string>>();
FindPaths(paths, validPaths, new List<string>() { "start" }, true);
FindPaths(paths, validPaths, new List<string>() { "START" }, true);
Logger.Log($"part2: {validPaths.Count}");
//validPaths.ForEach(path => Logger.Log($" {string.Join(',', path)}"));
}
}