#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, 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 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 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 data{"fbgdceah"}; std::map 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; } }