Add puzzles for 2022 Day 11.

This commit is contained in:
2022-12-11 07:47:51 +00:00
parent c9fa108996
commit e384f5b571
2 changed files with 411 additions and 0 deletions

203
2022/puzzle-11-01.cc Normal file
View File

@@ -0,0 +1,203 @@
//
// Created by Matthew Gretton-Dann on 09/12/2022.
//
#include <array>
#include <iostream>
#include <list>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
using Int = std::int64_t;
using UInt = std::uint64_t;
enum class Op { undef, add, mult, dbl, square };
struct Monkey
{
auto add_item(UInt score) { items_.push_back(score); }
auto op(Op op)
{
assert(op == Op::dbl || op == Op::square);
op_ = op;
}
auto op(Op op, UInt amt)
{
assert(op == Op::add || op == Op::mult);
op_ = op;
amt_ = amt;
}
auto test(UInt test) { test_ = test; }
auto true_monkey(UInt monkey) { true_monkey_ = monkey; }
auto false_monkey(UInt monkey) { false_monkey_ = monkey; }
[[nodiscard]] auto process_front() -> std::pair<UInt, UInt>
{
auto item{items_.front()};
items_.pop_front();
switch (op_) {
case Op::square:
item *= item;
break;
case Op::dbl:
item += item;
break;
case Op::add:
item += amt_;
break;
case Op::mult:
item *= amt_;
break;
default:
std::cerr << "Unexpected op\n";
std::abort();
}
item /= 3;
UInt const monkey{(item % test_ == 0) ? true_monkey_ : false_monkey_};
++inspection_count_;
return std::make_pair(item, monkey);
}
[[nodiscard]] auto empty() const -> bool { return items_.empty(); }
[[nodiscard]] auto score() const -> UInt { return inspection_count_; }
private:
std::list<UInt> items_;
Op op_{Op::undef};
UInt amt_{0};
UInt test_{0};
UInt true_monkey_{std::numeric_limits<Int>::max()};
UInt false_monkey_{std::numeric_limits<Int>::max()};
UInt inspection_count_{0};
};
struct State
{
auto populate(std::istream& is) -> bool
{
using namespace std::literals::string_literals;
std::string line;
auto it{monkies_.end()};
while (std::getline(is, line)) {
if (line.empty()) {
continue;
}
if (line.substr(0, 7) == "Monkey "s) {
it = monkies_.insert(monkies_.end(), Monkey{});
}
else if (line.substr(0, 18) == " Starting items: "s) {
assert(it != monkies_.end());
std::size_t pos{18};
while (pos < line.size()) {
if (line[pos] == ' ' || line[pos] == ',') {
++pos;
}
else if (std::isdigit(line[pos]) != 0) {
std::size_t len{0};
it->add_item(std::stoull(line.substr(pos), &len));
pos += len;
}
else {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
}
}
else if (line.substr(0, 23) == " Operation: new = old "s) {
assert(it != monkies_.end());
if (line[23] == '+') {
if (line.substr(25) == "old") {
it->op(Op::dbl);
}
else {
it->op(Op::add, std::stoull(line.substr(25)));
}
}
else {
if (line[23] != '*') {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
if (line.substr(25) == "old") {
it->op(Op::square);
}
else {
it->op(Op::mult, std::stoull(line.substr(25)));
}
}
}
else if (line.substr(0, 21) == " Test: divisible by "s) {
assert(it != monkies_.end());
it->test(std::stoull(line.substr(21)));
}
else if (line.substr(0, 29) == " If true: throw to monkey "s) {
assert(it != monkies_.end());
it->true_monkey(std::stoull(line.substr(29)));
}
else if (line.substr(0, 30) == " If false: throw to monkey "s) {
assert(it != monkies_.end());
it->false_monkey(std::stoull(line.substr(30)));
}
else {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
}
return true;
}
auto run_round()
{
unsigned m{0};
for (auto& monkey : monkies_) {
std::cout << "Monkey: " << m++ << '\n';
while (!monkey.empty()) {
auto [item, dest] = monkey.process_front();
std::cout << " Moving " << item << " to " << dest << '\n';
monkies_[dest].add_item(item);
}
}
}
[[nodiscard]] auto score() const -> UInt
{
UInt max1{0};
UInt max2{0};
for (auto const& monkey : monkies_) {
if (monkey.score() >= max1) {
max2 = max1;
max1 = monkey.score();
}
else if (monkey.score() >= max2) {
max2 = monkey.score();
}
}
std::cout << "Max score = " << max1 << " * " << max2 << " = " << max1 * max2 << "\n";
return max1 * max2;
}
std::vector<Monkey> monkies_;
};
auto main() -> int
{
State state;
if (!state.populate(std::cin)) {
return EXIT_FAILURE;
}
for (UInt i = 0; i < 20; ++i) {
state.run_round();
}
std::cout << "Score: " << state.score() << '\n';
return 0;
}

208
2022/puzzle-11-02.cc Normal file
View File

@@ -0,0 +1,208 @@
//
// Created by Matthew Gretton-Dann on 09/12/2022.
//
#include <array>
#include <cassert>
#include <iostream>
#include <list>
#include <numeric>
#include <string>
#include <utility>
#include <vector>
using Int = std::int64_t;
using UInt = std::uint64_t;
enum class Op { undef, add, mult, dbl, square };
struct Monkey
{
auto add_item(UInt score) { items_.push_back(score); }
auto op(Op op)
{
assert(op == Op::dbl || op == Op::square);
op_ = op;
}
auto op(Op op, UInt amt)
{
assert(op == Op::add || op == Op::mult);
op_ = op;
amt_ = amt;
}
auto test(UInt test) { test_ = test; }
auto true_monkey(UInt monkey) { true_monkey_ = monkey; }
auto false_monkey(UInt monkey) { false_monkey_ = monkey; }
[[nodiscard]] auto process_front() -> std::pair<UInt, UInt>
{
auto item{items_.front()};
auto const max{std::numeric_limits<UInt>::max()};
items_.pop_front();
switch (op_) {
case Op::square:
assert(item < (max / item));
item *= item;
break;
case Op::dbl:
assert(item < (max - item));
item += item;
break;
case Op::add:
assert(item < (max - amt_));
item += amt_;
break;
case Op::mult:
assert(item < (max / amt_));
item *= amt_;
break;
default:
std::cerr << "Unexpected op\n";
std::abort();
}
UInt const monkey{(item % test_ == 0) ? true_monkey_ : false_monkey_};
++inspection_count_;
return std::make_pair(item, monkey);
}
[[nodiscard]] auto empty() const -> bool { return items_.empty(); }
[[nodiscard]] auto score() const -> UInt { return inspection_count_; }
private:
std::list<UInt> items_;
Op op_{Op::undef};
UInt amt_{0};
UInt test_{0};
UInt true_monkey_{std::numeric_limits<Int>::max()};
UInt false_monkey_{std::numeric_limits<Int>::max()};
UInt inspection_count_{0};
};
struct State
{
auto populate(std::istream& is) -> bool
{
using namespace std::literals::string_literals;
std::string line;
auto it{monkies_.end()};
while (std::getline(is, line)) {
if (line.empty()) {
continue;
}
if (line.substr(0, 7) == "Monkey "s) {
it = monkies_.insert(monkies_.end(), Monkey{});
}
else if (line.substr(0, 18) == " Starting items: "s) {
assert(it != monkies_.end());
std::size_t pos{18};
while (pos < line.size()) {
if (line[pos] == ' ' || line[pos] == ',') {
++pos;
}
else if (std::isdigit(line[pos]) != 0) {
std::size_t len{0};
it->add_item(std::stoull(line.substr(pos), &len));
pos += len;
}
else {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
}
}
else if (line.substr(0, 23) == " Operation: new = old "s) {
assert(it != monkies_.end());
if (line[23] == '+') {
if (line.substr(25) == "old") {
it->op(Op::dbl);
}
else {
it->op(Op::add, std::stoull(line.substr(25)));
}
}
else {
if (line[23] != '*') {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
if (line.substr(25) == "old") {
it->op(Op::square);
}
else {
it->op(Op::mult, std::stoull(line.substr(25)));
}
}
}
else if (line.substr(0, 21) == " Test: divisible by "s) {
assert(it != monkies_.end());
auto div{std::stoull(line.substr(21))};
it->test(div);
mod_ *= div;
}
else if (line.substr(0, 29) == " If true: throw to monkey "s) {
assert(it != monkies_.end());
it->true_monkey(std::stoull(line.substr(29)));
}
else if (line.substr(0, 30) == " If false: throw to monkey "s) {
assert(it != monkies_.end());
it->false_monkey(std::stoull(line.substr(30)));
}
else {
std::cerr << "Unable to interpret: " << line << '\n';
return false;
}
}
return true;
}
auto run_round()
{
for (auto& monkey : monkies_) {
while (!monkey.empty()) {
auto [item, dest] = monkey.process_front();
monkies_[dest].add_item(item % mod_);
}
}
}
[[nodiscard]] auto score() const -> UInt
{
UInt max1{0};
UInt max2{0};
for (auto const& monkey : monkies_) {
if (monkey.score() >= max1) {
max2 = max1;
max1 = monkey.score();
}
else if (monkey.score() >= max2) {
max2 = monkey.score();
}
}
std::cout << "Max score = " << max1 << " * " << max2 << " = " << max1 * max2 << "\n";
return max1 * max2;
}
std::vector<Monkey> monkies_;
UInt mod_{1};
};
auto main() -> int
{
State state;
if (!state.populate(std::cin)) {
return EXIT_FAILURE;
}
for (UInt i = 0; i < 10'000; ++i) {
state.run_round();
}
std::cout << "Score: " << state.score() << '\n';
return 0;
}