AdventOfCode2021/source/day12/part1.d

73 lines
2.0 KiB
D
Raw Permalink Normal View History

2021-12-12 07:30:10 +00:00
module day12.part1;
import std.file;
import std.stdio;
import std.string;
import std.algorithm;
import std.conv;
import std.array;
bool isLarge(string name) {
return name.toUpper() == name;
}
void registerPath(ref string[][string] paths, string[] caves) {
if (caves[0] !in paths) {
paths[caves[0]] = [caves[1]];
} else {
paths[caves[0]] ~= caves[1];
}
if (caves[1] !in paths) {
paths[caves[1]] = [caves[0]];
} else {
paths[caves[1]] ~= caves[0];
}
}
uint[string] getVisitCounts(string[] history) {
uint[string] visitCounts;
foreach (p; history) {
if (p !in visitCounts) {
visitCounts[p] = 1;
} else {
visitCounts[p]++;
}
}
return visitCounts;
}
bool canVisit(string cave, string[] history) {
if (cave.isLarge) return true;
uint[string] visitCounts = getVisitCounts(history);
bool visitedSmallCaveTwice = false;
foreach (p, c; visitCounts) {
if (!p.isLarge && c > 1) {
visitedSmallCaveTwice = true;
break;
}
}
uint availablePathVisitCount = visitCounts.require(cave, 0);
return visitedSmallCaveTwice ? availablePathVisitCount < 1 : availablePathVisitCount < 2;
}
string[][] findPaths(ref string[][string] paths, string cave, string[] history) {
if (cave == "end") return [history ~ cave];
string[][] nextPaths = [];
foreach (availablePath; paths[cave]) {
if (availablePath == "start") continue;
if (canVisit(availablePath, history ~ cave)) nextPaths ~= findPaths(paths, availablePath, history ~ cave);
}
return nextPaths;
}
void passagePathing() {
string[] pathDescriptors = readText("source/day12/input.txt").strip.split("\n")
.map!(s => s.strip).array;
string[][string] paths;
foreach (desc; pathDescriptors) {
registerPath(paths, desc.split("-"));
}
findPaths(paths, "start", [])
.map!(p => p.joiner!(string[], string)(",").to!string)
.array.length.writeln;
}