Clean up day 9 solution
parent
ddc1947f59
commit
7a31a14936
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue