aocpp/2020/01.cpp

87 lines
1.8 KiB
C++
Raw Normal View History

2022-11-18 21:09:04 -08:00
#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);
}
2023-01-31 08:58:42 -08:00
std::sort(result.begin(), result.end());
2022-11-18 21:09:04 -08:00
return result;
}
2023-01-31 08:58:42 -08:00
auto Part1(std::vector<std::int64_t> const& entries) {
2022-11-18 21:09:04 -08:00
std::bitset<2020> numbers;
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"};
}
2023-01-31 08:58:42 -08:00
auto Part2(std::vector<std::int64_t> const& entries) {
2022-11-18 21:09:04 -08:00
std::bitset<2020> numbers;
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);
}
}
2023-01-31 08:58:42 -08:00
auto Main(std::istream & in) -> void
{
auto const entries {Parse(in)};
2022-11-18 21:09:04 -08:00
std::cout << "Part 1: " << Part1(entries) << std::endl;
std::cout << "Part 2: " << Part2(entries) << std::endl;
}