Add solution for 2016 Day 25
This commit is contained in:
1 parent
551df7ffb2
commit
a56cc80169
1 file changed
+173
-7
+173
-7
@@ -2,30 +2,196 @@
|
|||||||
|
|
||||||
namespace y2016::day25
|
namespace y2016::day25
|
||||||
{
|
{
|
||||||
REGISTER_DAY(2016, Day25, std::vector<int>, int);
|
enum class Operator
|
||||||
|
{
|
||||||
|
Cpy,
|
||||||
|
Inc,
|
||||||
|
Dec,
|
||||||
|
Jnz,
|
||||||
|
Out,
|
||||||
|
};
|
||||||
|
|
||||||
REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 1, 0);
|
struct Instruction
|
||||||
REGISTER_TEST(2016, Day25, Input, 1, 0);
|
{
|
||||||
REGISTER_TEST_EXAMPLE(2016, Day25, ExampleInput, 2, 0);
|
Operator op;
|
||||||
|
std::variant<char, int> arg1;
|
||||||
|
std::variant<char, int> arg2;
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_DAY(2016, Day25, std::vector<Instruction>, int);
|
||||||
|
|
||||||
|
REGISTER_TEST(2016, Day25, Input, 1, 182);
|
||||||
REGISTER_TEST(2016, Day25, Input, 2, 0);
|
REGISTER_TEST(2016, Day25, Input, 2, 0);
|
||||||
|
|
||||||
|
std::variant<char, int> 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)
|
READ_INPUT(input)
|
||||||
{
|
{
|
||||||
std::vector<int> vec;
|
std::vector<Instruction> vec;
|
||||||
std::string str;
|
std::string str;
|
||||||
while (getline(input, 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;
|
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<char>(instruction.arg2);
|
||||||
|
case Operator::Inc:
|
||||||
|
return std::holds_alternative<char>(instruction.arg1);
|
||||||
|
case Operator::Dec:
|
||||||
|
return std::holds_alternative<char>(instruction.arg1);
|
||||||
|
case Operator::Jnz:
|
||||||
|
return true;
|
||||||
|
case Operator::Out:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetRegisterIndex(const std::variant<char, int>& c)
|
||||||
|
{
|
||||||
|
return std::get<char>(c) - 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetValue(const std::vector<int>& registers, const std::variant<char, int>& data)
|
||||||
|
{
|
||||||
|
if (std::holds_alternative<int>(data))
|
||||||
|
return std::get<int>(data);
|
||||||
|
else
|
||||||
|
return registers[GetRegisterIndex(data)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Run(std::vector<Instruction> instructions, std::vector<int> 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)
|
OUTPUT1(input)
|
||||||
{
|
{
|
||||||
return 0;
|
int i = -1;
|
||||||
|
while (!Run(input, std::vector<int>{++i, 0, 0, 0}))
|
||||||
|
;
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
OUTPUT2(input)
|
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<int>{12, 0, 0, 0});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user