Add solution for 2016 Day 23
This commit is contained in:
1 parent
bec8be80a3
commit
edc2fd0b6c
3 files changed
+193
-8
No files matched your search
@@ -0,0 +1,7 @@
|
||||
cpy 2 a
|
||||
tgl a
|
||||
tgl a
|
||||
tgl a
|
||||
cpy 1 a
|
||||
dec a
|
||||
dec a
|
||||
+175
-8
@@ -2,30 +2,197 @@
|
||||
|
||||
namespace y2016::day23
|
||||
{
|
||||
REGISTER_DAY(2016, Day23, std::vector<int>, int);
|
||||
enum class Operator
|
||||
{
|
||||
Cpy,
|
||||
Inc,
|
||||
Dec,
|
||||
Jnz,
|
||||
Tgl
|
||||
};
|
||||
|
||||
REGISTER_TEST_EXAMPLE(2016, Day23, ExampleInput, 1, 0);
|
||||
REGISTER_TEST(2016, Day23, Input, 1, 0);
|
||||
REGISTER_TEST_EXAMPLE(2016, Day23, ExampleInput, 2, 0);
|
||||
REGISTER_TEST(2016, Day23, Input, 2, 0);
|
||||
struct Instruction
|
||||
{
|
||||
Operator op;
|
||||
std::variant<char, int> arg1;
|
||||
std::variant<char, int> arg2;
|
||||
};
|
||||
|
||||
REGISTER_DAY(2016, Day23, std::vector<Instruction>, int);
|
||||
|
||||
REGISTER_TEST(2016, Day23, Input, 1, 11415);
|
||||
REGISTER_TEST(2016, Day23, Input, 2, 479007975);
|
||||
|
||||
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)
|
||||
{
|
||||
std::vector<int> vec;
|
||||
std::vector<Instruction> 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] == 't')
|
||||
{
|
||||
instruction.op = Operator::Tgl;
|
||||
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::Tgl:
|
||||
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::Tgl:
|
||||
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)];
|
||||
}
|
||||
|
||||
int Run(std::vector<Instruction> instructions, std::vector<int> registers)
|
||||
{
|
||||
int i = 0;
|
||||
for (size_t pc = 0; pc < instructions.size(); pc++)
|
||||
{
|
||||
i++;
|
||||
if (!IsValid(instructions[pc]))
|
||||
continue;
|
||||
// The input program I got does a multiplication (a = b * d). So instead of using the ++, -- operators, calculate
|
||||
// it directly and set the registers to expected value after the operation is done.
|
||||
// Other inputs might have different pc position, and multiply different registers.
|
||||
if (pc == 4)
|
||||
{
|
||||
registers[0] = registers[1] * registers[3];
|
||||
registers[3] = 0;
|
||||
registers[2] = registers[1];
|
||||
pc = 9;
|
||||
}
|
||||
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::Tgl:
|
||||
{
|
||||
int offset = registers[GetRegisterIndex(instructions[pc].arg1)];
|
||||
if (pc + offset >= 0 && pc + offset < instructions.size())
|
||||
Toggle(instructions[pc + offset]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return registers[0];
|
||||
}
|
||||
|
||||
OUTPUT1(input)
|
||||
{
|
||||
return 0;
|
||||
return Run(input, std::vector<int>{7, 0, 0, 0});
|
||||
}
|
||||
|
||||
OUTPUT2(input)
|
||||
{
|
||||
return 0;
|
||||
return Run(input, std::vector<int>{12, 0, 0, 0});
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
#include <set>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "Array2D.h"
|
||||
@@ -33,6 +34,9 @@ static std::ostream& operator<<(std::ostream& stream, const std::map<T, S>& cont
|
||||
template <typename T, typename S>
|
||||
static std::ostream& operator<<(std::ostream& stream, const std::pair<T, S>& pair);
|
||||
|
||||
template <typename Arg1, typename Arg2, typename... Args>
|
||||
static std::ostream& operator<<(std::ostream& stream, const std::variant<Arg1, Arg2, Args...>& variant);
|
||||
|
||||
struct Helper
|
||||
{
|
||||
struct ScopedTraceErrorDisabler
|
||||
@@ -639,3 +643,10 @@ static std::ostream& operator<<(std::ostream& stream, const std::pair<T, S>& pai
|
||||
{
|
||||
return stream << "(" << pair.first << ", " << pair.second << ")";
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2, typename... Args>
|
||||
static std::ostream& operator<<(std::ostream& stream, const std::variant<Arg1, Arg2, Args...>& variant)
|
||||
{
|
||||
std::visit([&stream](const auto& value) { stream << value; }, variant);
|
||||
return stream;
|
||||
}
|
||||
Reference in new issue
Block a user