230 lines
5.9 KiB
C++
230 lines
5.9 KiB
C++
#include "common/aoc.h"
|
|
|
|
namespace y2016::day21
|
|
{
|
|
enum class Operator
|
|
{
|
|
Swap,
|
|
SwapLetter,
|
|
Rotate,
|
|
RotatePos,
|
|
Reverse,
|
|
Move
|
|
};
|
|
|
|
struct Instruction
|
|
{
|
|
Operator op;
|
|
int arg1;
|
|
int arg2;
|
|
};
|
|
|
|
REGISTER_DAY(2016, Day21, std::vector<Instruction>, std::string);
|
|
|
|
REGISTER_TEST_EXAMPLE(2016, Day21, ExampleInput, 1, "decab");
|
|
REGISTER_TEST(2016, Day21, Input, 1, "hcdefbag");
|
|
REGISTER_TEST(2016, Day21, Input, 2, "fbhaegdc");
|
|
|
|
READ_INPUT(input)
|
|
{
|
|
std::vector<Instruction> vec;
|
|
std::string str;
|
|
while (getline(input, str))
|
|
{
|
|
Instruction instruction;
|
|
std::stringstream ss{str};
|
|
if (Helper::StartsWith(str, "swap position"))
|
|
{
|
|
instruction.op = Operator::Swap;
|
|
ss >> "swap position " >> instruction.arg1 >> "with position " >> instruction.arg2;
|
|
}
|
|
else if (Helper::StartsWith(str, "swap letter"))
|
|
{
|
|
instruction.op = Operator::SwapLetter;
|
|
char c1, c2;
|
|
ss >> "swap letter " >> c1 >> "with letter " >> c2;
|
|
instruction.arg1 = c1;
|
|
instruction.arg2 = c2;
|
|
}
|
|
else if (Helper::StartsWith(str, "rotate left"))
|
|
{
|
|
instruction.op = Operator::Rotate;
|
|
ss >> "rotate left" >> instruction.arg1;
|
|
instruction.arg1 = -instruction.arg1;
|
|
}
|
|
else if (Helper::StartsWith(str, "rotate right"))
|
|
{
|
|
instruction.op = Operator::Rotate;
|
|
ss >> "rotate right" >> instruction.arg1;
|
|
}
|
|
else if (Helper::StartsWith(str, "rotate based"))
|
|
{
|
|
instruction.op = Operator::RotatePos;
|
|
char c;
|
|
ss >> "rotate based on position of letter " >> c;
|
|
instruction.arg1 = c;
|
|
}
|
|
else if (str[0] == 'r')
|
|
{
|
|
instruction.op = Operator::Reverse;
|
|
ss >> "reverse positions " >> instruction.arg1 >> "through " >> instruction.arg2;
|
|
}
|
|
else
|
|
{
|
|
instruction.op = Operator::Move;
|
|
ss >> "move position " >> instruction.arg1 >> "to position " >> instruction.arg2;
|
|
}
|
|
vec.emplace_back(instruction);
|
|
}
|
|
return vec;
|
|
}
|
|
|
|
OUTPUT1(input)
|
|
{
|
|
CyclicVector<char> data{isExample ? "abcde" : "abcdefgh"};
|
|
for (const auto& instruction : input)
|
|
{
|
|
switch (instruction.op)
|
|
{
|
|
case Operator::Swap:
|
|
{
|
|
std::swap(data[instruction.arg1], data[instruction.arg2]);
|
|
break;
|
|
}
|
|
case Operator::SwapLetter:
|
|
{
|
|
size_t i1 = data.Find(instruction.arg1);
|
|
size_t i2 = data.Find(instruction.arg2);
|
|
std::swap(data[i1], data[i2]);
|
|
break;
|
|
}
|
|
case Operator::Rotate:
|
|
{
|
|
data.Rotate(instruction.arg1);
|
|
break;
|
|
}
|
|
case Operator::RotatePos:
|
|
{
|
|
size_t pos = data.Find(instruction.arg1);
|
|
int additional = pos >= 4 ? 1 : 0;
|
|
data.Rotate(pos + 1 + additional);
|
|
break;
|
|
}
|
|
case Operator::Reverse:
|
|
{
|
|
for (size_t i = 0; i < (instruction.arg2 - instruction.arg1 + 1) / 2; i++)
|
|
{
|
|
std::swap(data[instruction.arg1 + i], data[instruction.arg2 - i]);
|
|
}
|
|
break;
|
|
}
|
|
case Operator::Move:
|
|
{
|
|
if (instruction.arg1 < instruction.arg2)
|
|
{
|
|
char c = data[instruction.arg1];
|
|
for (size_t i = instruction.arg1; i < instruction.arg2; i++)
|
|
{
|
|
data[i] = data[i + 1];
|
|
}
|
|
data[instruction.arg2] = c;
|
|
}
|
|
else
|
|
{
|
|
char c = data[instruction.arg1];
|
|
for (size_t i = instruction.arg1; i > instruction.arg2; i--)
|
|
{
|
|
data[i] = data[i - 1];
|
|
}
|
|
data[instruction.arg2] = c;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
std::string str;
|
|
for (size_t i = 0; i < data.size(); i++)
|
|
{
|
|
str.push_back(data[i]);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
OUTPUT2(input)
|
|
{
|
|
CyclicVector<char> data{"fbgdceah"};
|
|
std::map<int, int> rotatePosMap;
|
|
for (int i = 0; i < data.size(); i++)
|
|
{
|
|
int result = (i + i + 1 + (i >= 4 ? 1 : 0)) % data.size();
|
|
rotatePosMap.emplace(result, i - result);
|
|
}
|
|
for (int i = input.size() - 1; i >= 0; i--)
|
|
{
|
|
const auto& instruction = input[i];
|
|
switch (instruction.op)
|
|
{
|
|
case Operator::Swap:
|
|
{
|
|
std::swap(data[instruction.arg1], data[instruction.arg2]);
|
|
break;
|
|
}
|
|
case Operator::SwapLetter:
|
|
{
|
|
size_t i1 = data.Find(instruction.arg1);
|
|
size_t i2 = data.Find(instruction.arg2);
|
|
std::swap(data[i1], data[i2]);
|
|
break;
|
|
}
|
|
case Operator::Rotate:
|
|
{
|
|
data.Rotate(-instruction.arg1);
|
|
break;
|
|
}
|
|
case Operator::RotatePos:
|
|
{
|
|
size_t pos = data.Find(instruction.arg1);
|
|
data.Rotate(rotatePosMap[pos]);
|
|
break;
|
|
}
|
|
case Operator::Reverse:
|
|
{
|
|
for (size_t i = 0; i < (instruction.arg2 - instruction.arg1 + 1) / 2; i++)
|
|
{
|
|
std::swap(data[instruction.arg1 + i], data[instruction.arg2 - i]);
|
|
}
|
|
break;
|
|
}
|
|
case Operator::Move:
|
|
{
|
|
if (instruction.arg2 < instruction.arg1)
|
|
{
|
|
char c = data[instruction.arg2];
|
|
for (size_t i = instruction.arg2; i < instruction.arg1; i++)
|
|
{
|
|
data[i] = data[i + 1];
|
|
}
|
|
data[instruction.arg1] = c;
|
|
}
|
|
else
|
|
{
|
|
char c = data[instruction.arg2];
|
|
for (size_t i = instruction.arg2; i > instruction.arg1; i--)
|
|
{
|
|
data[i] = data[i - 1];
|
|
}
|
|
data[instruction.arg1] = c;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
std::string str;
|
|
for (auto c : data)
|
|
{
|
|
str.push_back(c);
|
|
}
|
|
return str;
|
|
}
|
|
}
|