Add solutions for 2022 day 21
This commit is contained in:
		
							
								
								
									
										95
									
								
								2022/puzzle-21-01.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								2022/puzzle-21-01.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| // | ||||
| // Created by Matthew Gretton-Dann on 16/12/2022. | ||||
| // | ||||
|  | ||||
| #include <array> | ||||
| #include <iostream> | ||||
| #include <map> | ||||
| #include <numeric> | ||||
| #include <stdexcept> | ||||
| #include <utility> | ||||
|  | ||||
| using Int = std::int64_t; | ||||
| using UInt = std::uint64_t; | ||||
| using Ints = std::vector<std::pair<Int, Int>>; | ||||
|  | ||||
| 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<std::string, Monkey> 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; | ||||
| } | ||||
							
								
								
									
										181
									
								
								2022/puzzle-21-02.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								2022/puzzle-21-02.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,181 @@ | ||||
| // | ||||
| // Created by Matthew Gretton-Dann on 16/12/2022. | ||||
| // | ||||
|  | ||||
| #include <array> | ||||
| #include <iostream> | ||||
| #include <map> | ||||
| #include <numeric> | ||||
| #include <stdexcept> | ||||
| #include <utility> | ||||
|  | ||||
| using Int = std::int64_t; | ||||
| using UInt = std::uint64_t; | ||||
| using Ints = std::vector<std::pair<Int, Int>>; | ||||
|  | ||||
| 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<Int>(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<std::string, Monkey>& 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<std::string, Monkey>& 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<std::string, Monkey> 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; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user