diff --git a/2022/puzzle-21-01.cc b/2022/puzzle-21-01.cc new file mode 100644 index 0000000..256eb37 --- /dev/null +++ b/2022/puzzle-21-01.cc @@ -0,0 +1,95 @@ +// +// Created by Matthew Gretton-Dann on 16/12/2022. +// + +#include +#include +#include +#include +#include +#include + +using Int = std::int64_t; +using UInt = std::uint64_t; +using Ints = std::vector>; + +using namespace std::string_literals; + +struct Monkey +{ + Monkey() = default; + + explicit Monkey(Int value) : value_(value), value_known_(true) {} + + Monkey(std::string lhs, char op, std::string rhs) + : lhs_(std::move(lhs)), rhs_(std::move(rhs)), op_(op) + { + } + + Monkey(Monkey const&) = default; + Monkey(Monkey&&) = default; + auto operator=(Monkey const&) -> Monkey& = default; + auto operator=(Monkey&&) -> Monkey& = default; + ~Monkey() = default; + + Int value_{0}; + bool value_known_{false}; + std::string lhs_; + std::string rhs_; + char op_{'\0'}; +}; + +auto calculate(Int lhs, char op, Int rhs) +{ + switch (op) { + case '+': + return lhs + rhs; + case '-': + return lhs - rhs; + case '*': + return lhs * rhs; + case '/': + return lhs / rhs; + default: + std::abort(); + } +} + +auto main() -> int +{ + std::string line; + std::map monkies; + + while (std::getline(std::cin, line)) { + std::string const id(line.substr(0, 4)); + if (std::isdigit(line[6]) != 0) { + auto [it, success] = monkies.insert({id, Monkey(std::stoll(line.substr(6)))}); + assert(success); + } + else { + auto [it, success] = + monkies.insert({id, Monkey(line.substr(6, 4), line[11], line.substr(13))}); + assert(success); + } + } + + while (!monkies["root"s].value_known_) { + for (auto& monkey : monkies) { + if (monkey.second.value_known_) { + continue; + } + + auto lhs = monkies.find(monkey.second.lhs_); + auto rhs = monkies.find(monkey.second.rhs_); + if (!lhs->second.value_known_ || !rhs->second.value_known_) { + continue; + } + + monkey.second.value_ = calculate(lhs->second.value_, monkey.second.op_, rhs->second.value_); + monkey.second.value_known_ = true; + } + } + + std::cout << "Root's value: " << monkies["root"s].value_ << "\n"; + return EXIT_SUCCESS; +} diff --git a/2022/puzzle-21-02.cc b/2022/puzzle-21-02.cc new file mode 100644 index 0000000..38533ff --- /dev/null +++ b/2022/puzzle-21-02.cc @@ -0,0 +1,181 @@ +// +// Created by Matthew Gretton-Dann on 16/12/2022. +// + +#include +#include +#include +#include +#include +#include + +using Int = std::int64_t; +using UInt = std::uint64_t; +using Ints = std::vector>; + +using namespace std::string_literals; + +struct Monkey +{ + Monkey() = default; + + explicit Monkey(Int value) : value_(value), value_known_(true) {} + + Monkey(std::string lhs, char op, std::string rhs) + : lhs_(std::move(lhs)), rhs_(std::move(rhs)), op_(op) + { + } + + static auto human() -> Monkey + { + Monkey monkey; + monkey.value_known_ = false; + monkey.op_ = 'h'; + return monkey; + } + + Monkey(Monkey const&) = default; + Monkey(Monkey&&) = default; + auto operator=(Monkey const&) -> Monkey& = default; + auto operator=(Monkey&&) -> Monkey& = default; + ~Monkey() = default; + + Int value_{0}; + bool value_known_{false}; + std::string lhs_; + std::string rhs_; + char op_{'\0'}; +}; + +auto calculate(Int lhs, char op, Int rhs) +{ + switch (op) { + case '+': + return lhs + rhs; + case '-': + return lhs - rhs; + case '*': + return lhs * rhs; + case '/': + return lhs / rhs; + case '=': + return static_cast(lhs == rhs ? 1 : 0); + default: + std::abort(); + } +} + +auto find_lhs(Int result, char op, Int rhs) +{ + switch (op) { + case '+': // result = lhs + rhs -> lhs = result - rhs; + return result - rhs; + case '-': // result = lhs - rhs -> lhs = result + rhs; + return result + rhs; + case '*': // result = lhs * rhs -> lhs = result / rhs + return result / rhs; + case '/': // result = lhs / rhs -> lhs = result * rhs; + return result * rhs; + case '=': + return rhs; + default: + std::abort(); + } +} + +auto find_rhs(Int result, Int lhs, char op) +{ + switch (op) { + case '+': // result = lhs + rhs -> rhs = result - lhs; + return result - lhs; + case '-': // result = lhs - rhs -> rhs = lhs - result; + return lhs - result; + case '*': // result = lhs * rhs -> rhs = result / lhs + return result / lhs; + case '/': // result = lhs / rhs -> rhs = lhs / result; + return lhs / result; + case '=': + return lhs; + default: + std::abort(); + } +} + +auto calculate_up(std::map& monkies) +{ + bool changed{true}; + while (changed) { + changed = false; + for (auto& monkey : monkies) { + if (monkey.second.value_known_) { + continue; + } + + auto lhs = monkies.find(monkey.second.lhs_); + auto rhs = monkies.find(monkey.second.rhs_); + if (!lhs->second.value_known_ || !rhs->second.value_known_) { + continue; + } + if (lhs->second.op_ == 'h' || rhs->second.op_ == 'h') { + continue; + } + + monkey.second.value_ = calculate(lhs->second.value_, monkey.second.op_, rhs->second.value_); + monkey.second.value_known_ = true; + changed = true; + } + } +} + +auto find_human_value(std::map& monkies) +{ + auto monkey{monkies.find("root"s)}; + monkey->second.value_ = 1; + monkey->second.value_known_ = true; + while (monkey->first != "humn"s) { + auto lhs{monkies.find(monkey->second.lhs_)}; + auto rhs{monkies.find(monkey->second.rhs_)}; + assert(lhs->second.value_known_ ^ rhs->second.value_known_); + if (!lhs->second.value_known_) { + lhs->second.value_ = find_lhs(monkey->second.value_, monkey->second.op_, rhs->second.value_); + lhs->second.value_known_ = true; + monkey = lhs; + } + if (!rhs->second.value_known_) { + rhs->second.value_ = find_rhs(monkey->second.value_, lhs->second.value_, monkey->second.op_); + rhs->second.value_known_ = true; + monkey = rhs; + } + } +} + +auto main() -> int +{ + std::string line; + std::map monkies; + + while (std::getline(std::cin, line)) { + std::string const id(line.substr(0, 4)); + if (std::isdigit(line[6]) != 0) { + if (id == "humn"s) { + auto [it, success] = monkies.insert({id, Monkey::human()}); + assert(success); + } + else { + auto [it, success] = monkies.insert({id, Monkey(std::stoll(line.substr(6)))}); + assert(success); + } + } + else { + char const op{(id == "root"s) ? '=' : line[11]}; + auto [it, success] = monkies.insert({id, Monkey(line.substr(6, 4), op, line.substr(13))}); + assert(success); + } + } + + calculate_up(monkies); + find_human_value(monkies); + + std::cout << "Human's value: " << monkies["humn"s].value_ << "\n"; + return EXIT_SUCCESS; +}