parent
6fefc1c325
commit
2adbdf08ce
|
@ -58,6 +58,39 @@ Value getOrDefault(const std::map<Key, Value> &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<int> &adapters, std::unordered_map<int, long> &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<int> &input) {
|
int part1(const std::vector<int> &input) {
|
||||||
std::map<int, int> differenceCounts;
|
std::map<int, int> differenceCounts;
|
||||||
std::vector<int> adapters(input);
|
std::vector<int> adapters(input);
|
||||||
|
@ -74,16 +107,9 @@ int part1(const std::vector<int> &input) {
|
||||||
long part2(const std::vector<int> &input) {
|
long part2(const std::vector<int> &input) {
|
||||||
std::vector<int> adapters(input);
|
std::vector<int> adapters(input);
|
||||||
prepareInput(adapters);
|
prepareInput(adapters);
|
||||||
// Dynamic programming approach that counts the number of ways to get to each point by backshifting
|
std::unordered_map<int, long> counts;
|
||||||
std::vector<long> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return counts.back();
|
return solvePart2WithGraph(adapters, counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
Loading…
Reference in New Issue