Add puzzles for 2022 Day 11.
This commit is contained in:
203
2022/puzzle-11-01.cc
Normal file
203
2022/puzzle-11-01.cc
Normal 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
208
2022/puzzle-11-02.cc
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user