Clean up day 9 solution

master
Nick Krichevsky 2020-12-09 01:05:10 -05:00
parent ddc1947f59
commit 7a31a14936
1 changed files with 27 additions and 41 deletions

View File

@ -6,7 +6,6 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <numeric> #include <numeric>
#include <optional>
#include <regex> #include <regex>
#include <set> #include <set>
#include <string_view> #include <string_view>
@ -25,6 +24,11 @@ std::vector<std::string> readInput(const std::string &filename) {
return input; return input;
} }
/**
* Convert a vector of strings to a vector of numbers
* @param input The input for the puzzle
* @return std::vector<long> The puzzle input as numbers
*/
std::vector<long> convertInputToNumbers(const std::vector<std::string> &input) { std::vector<long> convertInputToNumbers(const std::vector<std::string> &input) {
std::vector<long> converted; std::vector<long> converted;
converted.reserve(input.size()); converted.reserve(input.size());
@ -35,57 +39,38 @@ std::vector<long> convertInputToNumbers(const std::vector<std::string> &input) {
return converted; return converted;
} }
/**
* Find a number in the range that, it, plus candidate, equals total.
* @tparam Iter
* @param total The number to sum to
* @param candidate The number to sum with
* @param start The start of the range
* @param end The end of the range
* @return bool If such a number exists, return true, false otherwise.
*/
template <typename Iter>
bool numberThatSumsInRange(int total, int candidate, Iter start, Iter end) {
for (Iter it = start; it != end; it++) {
// std::cout << *it << std::endl;
if (candidate + *it == total) {
return true;
}
}
return false;
}
long part1(const std::vector<long> &numbers) { long part1(const std::vector<long> &numbers) {
for (auto checkIterator = numbers.begin() + PREAMBLE_SIZE; checkIterator != numbers.end(); checkIterator++) { for (auto totalIterator = numbers.cbegin() + PREAMBLE_SIZE; totalIterator != numbers.cend(); totalIterator++) {
auto rangeStart = checkIterator - PREAMBLE_SIZE; // Though we skip the first PREAMBLE_SIZE to find the number to sum to, we want to start summing as if we didn't
auto rangeEnd = checkIterator; // do that
std::optional<int> foundNumber; auto rangeStart = totalIterator - PREAMBLE_SIZE;
for (auto it = rangeStart; it != rangeEnd; it++) { auto rangeEnd = totalIterator;
if (numberThatSumsInRange(*checkIterator, *it, rangeStart, rangeEnd)) { auto result = std::find_if(rangeStart, rangeEnd, [=](long candidate1) {
foundNumber = *checkIterator; auto candidate2 = std::find_if(
break; rangeStart, rangeEnd, [=](long candidate2) { return candidate1 + candidate2 == *totalIterator; });
}
}
if (!foundNumber.has_value()) { return candidate2 != rangeEnd;
return *checkIterator; });
if (result == rangeEnd) {
return *totalIterator;
} }
} }
throw std::invalid_argument("No solution in input"); throw std::invalid_argument("No solution in input");
} }
long part2(const std::vector<long> &numbers) { long part2(const std::vector<long> &numbers, long desired) {
long desired = part1(numbers);
for (auto rangeStartIterator = numbers.begin(); rangeStartIterator != numbers.end(); rangeStartIterator++) { for (auto rangeStartIterator = numbers.begin(); rangeStartIterator != numbers.end(); rangeStartIterator++) {
for (auto rangeEndIterator = rangeStartIterator + 1; rangeEndIterator != numbers.end(); rangeEndIterator++) { for (auto rangeEndIterator = rangeStartIterator + 1; rangeEndIterator != numbers.end(); rangeEndIterator++) {
// Sum all the numbers between our two iterators
auto total = std::accumulate( auto total = std::accumulate(
rangeStartIterator, rangeEndIterator, 0, [](int num, int total) { return num + total; }); rangeStartIterator, rangeEndIterator, 0, [](int num, int total) { return num + total; });
// If this total is our desired, we're done
if (total == desired) { if (total == desired) {
auto min = std::min_element(rangeStartIterator, rangeEndIterator); auto minIterator = std::min_element(rangeStartIterator, rangeEndIterator);
auto max = std::max_element(rangeStartIterator, rangeEndIterator); auto maxIterator = std::max_element(rangeStartIterator, rangeEndIterator);
return *min + *max; return *minIterator + *maxIterator;
} }
} }
} }
@ -102,6 +87,7 @@ int main(int argc, char *argv[]) {
auto input = readInput(argv[1]); auto input = readInput(argv[1]);
auto numbers = convertInputToNumbers(input); auto numbers = convertInputToNumbers(input);
std::cout << part1(numbers) << std::endl; auto part1Answer = part1(numbers);
std::cout << part2(numbers) << std::endl; std::cout << part1Answer << std::endl;
std::cout << part2(numbers, part1Answer) << std::endl;
} }