From a56cc8016912385f41584ff0c0f88f491705d24a Mon Sep 17 00:00:00 2001 From: Thraix Date: Fri, 4 Sep 2026 20:54:17 +0200 Subject: [PATCH] Add solution for 2016 Day 25 --- src/2016/Day25.cpp | 180 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 7 deletions(-) diff --git a/src/2016/Day25.cpp b/src/2016/Day25.cpp index dc4a26b..61e7f96 100644 --- a/src/2016/Day25.cpp +++ b/src/2016/Day25.cpp @@ -2,30 +2,196 @@ namespace y2016::day25 { - REGISTER_DAY(2016, Day25, std::vector, int); + enum class Operator + { + Cpy, + Inc, + Dec, + Jnz, + Out, + }; - REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 1, 0); - REGISTER_TEST(2016, Day25, Input, 1, 0); - REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 2, 0); + struct Instruction + { + Operator op; + std::variant arg1; + std::variant arg2; + }; + + REGISTER_DAY(2016, Day25, std::vector, int); + + REGISTER_TEST(2016, Day25, Input, 1, 182); REGISTER_TEST(2016, Day25, Input, 2, 0); + std::variant ReadArg(const std::string& str, int arg) + { + size_t pos = str.find(' '); + int i = 0; + while (i < arg) + { + pos = str.find(' ', pos + 1); + i++; + } + + if (str[pos + 1] >= 'a' && str[pos + 1] <= 'd') + return str[pos + 1]; + + return (int)std::atoi(str.c_str() + pos + 1); + } + READ_INPUT(input) { - std::vector vec; + std::vector vec; std::string str; while (getline(input, str)) { + Instruction instruction; + if (str[0] == 'c') + { + instruction.op = Operator::Cpy; + instruction.arg1 = ReadArg(str, 0); + instruction.arg2 = ReadArg(str, 1); + } + else if (str[0] == 'i') + { + instruction.op = Operator::Inc; + instruction.arg1 = ReadArg(str, 0); + } + else if (str[0] == 'd') + { + instruction.op = Operator::Dec; + instruction.arg1 = ReadArg(str, 0); + } + else if (str[0] == 'j') + { + instruction.op = Operator::Jnz; + instruction.arg1 = ReadArg(str, 0); + instruction.arg2 = ReadArg(str, 1); + } + else if (str[0] == 'o') + { + instruction.op = Operator::Out; + instruction.arg1 = ReadArg(str, 0); + } + vec.emplace_back(instruction); } return vec; } + void Toggle(Instruction& instruction) + { + switch (instruction.op) + { + case Operator::Cpy: + instruction.op = Operator::Jnz; + break; + case Operator::Inc: + instruction.op = Operator::Dec; + break; + case Operator::Dec: + instruction.op = Operator::Inc; + break; + case Operator::Jnz: + instruction.op = Operator::Cpy; + break; + case Operator::Out: + instruction.op = Operator::Inc; + break; + } + } + + bool IsValid(const Instruction& instruction) + { + switch (instruction.op) + { + case Operator::Cpy: + return std::holds_alternative(instruction.arg2); + case Operator::Inc: + return std::holds_alternative(instruction.arg1); + case Operator::Dec: + return std::holds_alternative(instruction.arg1); + case Operator::Jnz: + return true; + case Operator::Out: + return true; + } + return false; + } + + int GetRegisterIndex(const std::variant& c) + { + return std::get(c) - 'a'; + } + + int GetValue(const std::vector& registers, const std::variant& data) + { + if (std::holds_alternative(data)) + return std::get(data); + else + return registers[GetRegisterIndex(data)]; + } + + bool Run(std::vector instructions, std::vector registers) + { + int count = 0; + for (size_t pc = 0; pc < instructions.size(); pc++) + { + // From analysis of the input, it loops the same output every time we get to pc = 8. + // As such, if we get there, and count is > 0, we know that the signal alternates, since we've already returned + // false if the output to this point is not alternating + if (pc == 8 && count > 0) + return true; + switch (instructions[pc].op) + { + case Operator::Cpy: + { + int number = GetValue(registers, instructions[pc].arg1); + registers[GetRegisterIndex(instructions[pc].arg2)] = number; + break; + } + case Operator::Inc: + { + registers[GetRegisterIndex(instructions[pc].arg1)]++; + break; + } + case Operator::Dec: + { + registers[GetRegisterIndex(instructions[pc].arg1)]--; + break; + } + case Operator::Jnz: + { + int value = GetValue(registers, instructions[pc].arg1); + if (value != 0) + pc += GetValue(registers, instructions[pc].arg2) - 1; + break; + } + case Operator::Out: + { + if (GetValue(registers, instructions[pc].arg1) != count % 2) + return false; + count++; + } + break; + } + } + return false; + } + OUTPUT1(input) { - return 0; + int i = -1; + while (!Run(input, std::vector{++i, 0, 0, 0})) + ; + return i; } OUTPUT2(input) { - return 0; + std::cout << " ___ ___" << std::endl; + std::cout << " (o o) (o o)" << std::endl; + std::cout << "( V ) MERRY CHRISTMAS! ( V )" << std::endl; + std::cout << "--m-m----------------------m-m--" << std::endl; + return Run(input, std::vector{12, 0, 0, 0}); } }