diff --git a/source/app.d b/source/app.d index 153ffa9..7da990b 100644 --- a/source/app.d +++ b/source/app.d @@ -1,7 +1,7 @@ import std.stdio; -import day11.part1; +import day12.part1; void main() { - dumboOctopus(); + passagePathing(); } diff --git a/source/day12/input.txt b/source/day12/input.txt new file mode 100644 index 0000000..1d5c9fe --- /dev/null +++ b/source/day12/input.txt @@ -0,0 +1,24 @@ +re-js +qx-CG +start-js +start-bj +qx-ak +js-bj +ak-re +CG-ak +js-CG +bj-re +ak-lg +lg-CG +qx-re +WP-ak +WP-end +re-lg +end-ak +WP-re +bj-CG +qx-start +bj-WP +JG-lg +end-lg +lg-iw diff --git a/source/day12/part1.d b/source/day12/part1.d new file mode 100644 index 0000000..5ecded9 --- /dev/null +++ b/source/day12/part1.d @@ -0,0 +1,73 @@ +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; +} \ No newline at end of file diff --git a/source/day12/test_input.txt b/source/day12/test_input.txt new file mode 100644 index 0000000..6fd8c41 --- /dev/null +++ b/source/day12/test_input.txt @@ -0,0 +1,7 @@ +start-A +start-b +A-c +A-b +b-d +A-end +b-end diff --git a/source/day12/test_input2.txt b/source/day12/test_input2.txt new file mode 100644 index 0000000..62cc714 --- /dev/null +++ b/source/day12/test_input2.txt @@ -0,0 +1,10 @@ +dc-end +HN-start +start-kj +dc-start +dc-HN +LN-dc +HN-end +kj-sa +kj-HN +kj-dc diff --git a/source/day12/test_input3.txt b/source/day12/test_input3.txt new file mode 100644 index 0000000..65f3833 --- /dev/null +++ b/source/day12/test_input3.txt @@ -0,0 +1,18 @@ +fs-end +he-DX +fs-he +start-DX +pj-DX +end-zg +zg-sl +zg-pj +pj-he +RW-he +fs-DX +pj-RW +zg-RW +start-pj +he-WI +zg-he +pj-fs +start-RW