87 lines
1.8 KiB
C++
87 lines
1.8 KiB
C++
|
#include <algorithm>
|
||
|
#include <bitset>
|
||
|
#include <cstdint>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <iterator>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <doctest.h>
|
||
|
|
||
|
#include <aocpp/Startup.hpp>
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
auto Parse(std::istream & in) -> std::vector<std::int64_t>
|
||
|
{
|
||
|
std::vector<int64_t> result;
|
||
|
std::int64_t x;
|
||
|
while (in >> x) {
|
||
|
result.push_back(x);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
auto Part1(std::vector<std::int64_t> entries) {
|
||
|
std::bitset<2020> numbers;
|
||
|
std::sort(entries.begin(), entries.end());
|
||
|
for (auto const i : entries) {
|
||
|
if (i >= 2020) {
|
||
|
break;
|
||
|
}
|
||
|
numbers.set(i);
|
||
|
}
|
||
|
for (auto const i : entries) {
|
||
|
if (numbers.test(2020 - i)) {
|
||
|
return (2020 - i) * i;
|
||
|
}
|
||
|
}
|
||
|
throw std::runtime_error{"no part 1 solution"};
|
||
|
}
|
||
|
|
||
|
auto Part2(std::vector<std::int64_t> entries) {
|
||
|
std::bitset<2020> numbers;
|
||
|
std::sort(entries.begin(), entries.end());
|
||
|
for (auto const i : entries) {
|
||
|
if (i >= 2020) { break; }
|
||
|
if (i < 2020) { numbers.set(i); }
|
||
|
}
|
||
|
|
||
|
for (auto it1 = entries.begin(); it1 != entries.end(); it1++) {
|
||
|
for (auto it2 = std::next(it1); it2 != entries.end(); it2++) {
|
||
|
auto target = 2020 - (*it1) - (*it2);
|
||
|
if (target < 0) break;
|
||
|
if (target < 2020 && numbers.test(target)) { return target * *it1 * *it2;}
|
||
|
}
|
||
|
}
|
||
|
throw std::runtime_error{"no part 2 solution"};
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
TEST_SUITE("documented examples") {
|
||
|
std::istringstream in {
|
||
|
"1721\n"
|
||
|
"979\n"
|
||
|
"366\n"
|
||
|
"299\n"
|
||
|
"675\n"
|
||
|
"1456\n"};
|
||
|
auto entries = Parse(in);
|
||
|
|
||
|
TEST_CASE("part 1") {
|
||
|
REQUIRE(Part1(entries) == 514579);
|
||
|
}
|
||
|
|
||
|
TEST_CASE("part 2") {
|
||
|
REQUIRE(Part2(entries) == 241861950);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
auto main(int argc, char** argv) -> int {
|
||
|
auto entries = Parse(aocpp::Startup(argc, argv));
|
||
|
std::cout << "Part 1: " << Part1(entries) << std::endl;
|
||
|
std::cout << "Part 2: " << Part2(entries) << std::endl;
|
||
|
}
|