From 2adbdf08ce06f4cfa62554d8af97d522cbacbe41 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Thu, 10 Dec 2020 04:17:27 -0500 Subject: [PATCH] Solve part 2 on my own :) Custom graph based solution --- day10/day10.cpp | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/day10/day10.cpp b/day10/day10.cpp index d49e7db..62f47cd 100644 --- a/day10/day10.cpp +++ b/day10/day10.cpp @@ -58,6 +58,39 @@ Value getOrDefault(const std::map &map, Key key, Value defaultValue) } } +/** + * Finds the number of paths from the given source node to the target (the end of the adapters lsit) + * Based on algorithm from: + * https://cs.stackexchange.com/questions/3078/algorithm-that-finds-the-number-of-simple-paths-from-s-to-t-in-g + * @param adapters The puzzle input, prepared by prepareAdapters + * @param numPaths A count of the number of paths + * @param source The node to start from + * @return long + */ +long solvePart2WithGraph(const std::vector &adapters, std::unordered_map &numPaths, int source = 0) { + int target = adapters.size() - 1; + if (source == target) { + return 1; + } + + // If we already know the number of paths to source, we're done + auto pathsToSource = numPaths.find(source); + if (pathsToSource != numPaths.end()) { + return pathsToSource->second; + } + + // Find the number of paths by just checking all off the neighbors + // Something is defined as a neighbor if we can get to it by addding [1, 3] + long total = 0; + for (int i = source + 1; i < adapters.size() && adapters.at(i) - adapters.at(source) <= MAX_VOLTAGE_DELTA; i++) { + total += solvePart2WithGraph(adapters, numPaths, i); + } + + numPaths.emplace(source, total); + + return total; +} + int part1(const std::vector &input) { std::map differenceCounts; std::vector adapters(input); @@ -74,16 +107,9 @@ int part1(const std::vector &input) { long part2(const std::vector &input) { std::vector adapters(input); prepareInput(adapters); - // Dynamic programming approach that counts the number of ways to get to each point by backshifting - std::vector counts(adapters.back() + 1, 0); - counts.at(0) = 1; - for (auto it = std::next(adapters.cbegin()); it != adapters.cend(); it++) { - for (int i = *it; i >= 0 && i >= *it - MAX_VOLTAGE_DELTA; i--) { - counts.at(*it) += counts.at(i); - } - } + std::unordered_map counts; - return counts.back(); + return solvePart2WithGraph(adapters, counts); } int main(int argc, char *argv[]) {