73 lines
2.0 KiB
D
73 lines
2.0 KiB
D
|
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;
|
||
|
}
|