Files
AdventOfCode/src/2022/Day11.cpp
T

147 lines
3.8 KiB
C++

#include "common/aoc.h"
namespace y$1::day11
{
enum Op
{
Add,
Mul
};
struct Old
{
};
struct Monkey
{
std::vector<int64_t> items;
std::variant<int, Old> bin1;
std::variant<int, Old> bin2;
int divisible;
Op op;
int monkeyTrue;
int monkeyFalse;
};
REGISTER_DAY(2022, Day11, std::vector<Monkey>, int64_t);
REGISTER_TEST_EXAMPLE(2022, Day11, ExampleInput, 1, 10605);
REGISTER_TEST(2022, Day11, Input, 1, 120756);
REGISTER_TEST_EXAMPLE(2022, Day11, ExampleInput, 2, 2713310158);
REGISTER_TEST(2022, Day11, Input, 2, 39109444654);
template <typename Func>
void Round(std::vector<Monkey>& monkeys, std::vector<int64_t>& inspections, Func worryManagement)
{
for (int j = 0; j < monkeys.size(); j++)
{
for (auto item : monkeys[j].items)
{
inspections[j]++;
int64_t i1 = std::holds_alternative<Old>(monkeys[j].bin1) ? item : std::get<int>(monkeys[j].bin1);
int64_t i2 = std::holds_alternative<Old>(monkeys[j].bin2) ? item : std::get<int>(monkeys[j].bin2);
int64_t val;
if (monkeys[j].op == Op::Add)
val = i1 + i2;
else if (monkeys[j].op == Op::Mul)
val = i1 * i2;
val = worryManagement(val);
if (val % monkeys[j].divisible == 0)
monkeys[monkeys[j].monkeyTrue].items.emplace_back(val);
else
monkeys[monkeys[j].monkeyFalse].items.emplace_back(val);
}
monkeys[j].items.clear();
}
}
READ_INPUT(input)
{
std::string str;
std::vector<Monkey> monkeys;
while (std::getline(input, str))
{
Monkey monkey;
{ // items
std::getline(input, str);
std::stringstream ss{str};
ss >> "Starting items: ";
while (std::getline(ss, str, ','))
monkey.items.emplace_back(std::stoi(str));
}
{ // operator
std::getline(input, str);
std::stringstream ss{str};
ss >> "Operation: new = ";
ss >> str;
if (str == "old")
monkey.bin1 = Old{};
else
monkey.bin1 = std::stoi(str);
char c;
ss >> c;
if (c == '+')
monkey.op = Op::Add;
else if (c == '*')
monkey.op = Op::Mul;
ss >> str;
if (str == "old")
monkey.bin2 = Old{};
else
monkey.bin2 = std::stoi(str);
}
{ // Test
std::getline(input, str);
std::stringstream ss{str};
ss >> "Test: divisible by " >> monkey.divisible;
}
{ // True
std::getline(input, str);
std::stringstream ss{str};
ss >> "If true: throw to monkey " >> monkey.monkeyTrue;
}
{ // False
std::getline(input, str);
std::stringstream ss{str};
ss >> "If false: throw to monkey " >> monkey.monkeyFalse;
}
std::getline(input, str);
monkeys.emplace_back(monkey);
}
return monkeys;
}
OUTPUT1(input)
{
std::vector<int64_t> inspections;
inspections.resize(input.size());
std::vector<Monkey> monkeys = input;
for (int i = 0; i < 20; i++)
{
Round(monkeys, inspections, [](int64_t val) { return val / 3; });
}
std::sort(inspections.begin(), inspections.end());
return inspections[inspections.size() - 1] * inspections[inspections.size() - 2];
}
OUTPUT2(input)
{
std::vector<int64_t> inspections;
inspections.resize(input.size());
std::vector<Monkey> monkeys = input;
int mod = 1;
for (auto& monkey : monkeys)
{
mod *= monkey.divisible;
}
for (int i = 0; i < 10000; i++)
{
Round(monkeys, inspections, [mod](int64_t val) { return val % mod; });
}
std::sort(inspections.begin(), inspections.end());
return inspections[inspections.size() - 1] * inspections[inspections.size() - 2];
}
}