#include #include #include #include #include #include #include #include #include #include constexpr auto MAX_VOLTAGE_DELTA = 3; std::vector readInput(const std::string &filename) { std::vector input; std::string line; std::ifstream file(filename); while (std::getline(file, line)) { input.push_back(line); } return input; } /** * Convert a vector of strings to a vector of numbers * @param input The input for the puzzle * @return std::vector The puzzle input as numbers */ std::vector convertInputToNumbers(const std::vector &input) { std::vector converted; converted.reserve(input.size()); std::transform(input.cbegin(), input.cend(), std::back_inserter(converted), [](const std::string &line) { return std::stol(line); }); return converted; } /** * Add the outlet and max voltage to the input list, and sort it * @param input The input for the puzzle */ void prepareInput(std::vector &input) { int max_voltage = *std::max_element(input.cbegin(), input.cend()) + MAX_VOLTAGE_DELTA; input.push_back(0); input.push_back(max_voltage); std::sort(input.begin(), input.end()); } /** * 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); prepareInput(adapters); for (auto it = adapters.cbegin(); it != adapters.end() && std::next(it) != adapters.cend(); it++) { auto difference = *std::next(it) - *it; differenceCounts[difference]++; } return differenceCounts[1] * differenceCounts[3]; } long part2(const std::vector &input) { std::vector adapters(input); prepareInput(adapters); std::unordered_map counts; return solvePart2WithGraph(adapters, counts); } int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << argv[0] << " " << std::endl; return 1; } auto input = readInput(argv[1]); auto numericInput = convertInputToNumbers(input); std::cout << part1(numericInput) << std::endl; std::cout << part2(numericInput) << std::endl; }