advent_of_code/2020/day8.cpp

113 lines
3.5 KiB
C++

/*******************************************************************************
*
* Copyright (c) 2020 Gnarwhal
*
* -----------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files(the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include "types.hpp"
enum OpCode { Acc, Jmp, Nop };
struct Op{ OpCode code; i32 num; };
auto extract_op(const std::string & string) -> Op {
auto op = Op{ Nop, 0 };
auto op_code_str = string.substr(0, 3);
if (string.substr(0, 3) == "acc") { op.code = Acc; }
else if (string.substr(0, 3) == "jmp") { op.code = Jmp; }
else if (string.substr(0, 3) == "nop") { op.code = Nop; }
op.num = std::stoi(string.substr(4, string.size() - 4));
return op;
}
struct State{ u32 isp; i32 acc; };
auto execute(State & state, const std::vector<Op> & ops) -> void {
switch (ops[state.isp].code) {
case Acc: state.acc += ops[state.isp].num; ++state.isp; break;
case Jmp: state.isp += ops[state.isp].num; break;
case Nop: ++state.isp; break;
}
}
auto attempt_swap(State & state, std::vector<Op> & ops) -> bool {
if (ops[state.isp].code == Jmp) {
ops[state.isp].code = Nop;
} else if (ops[state.isp].code == Nop) {
ops[state.isp].code = Jmp;
} else {
return false;
}
auto local_state = state;
auto executed = std::vector<bool>(ops.size());
while (local_state.isp < ops.size() && !executed[local_state.isp]) {
executed[local_state.isp] = true;
execute(local_state, ops);
}
if (local_state.isp >= ops.size()) {
state = local_state;
return true;
} else if (ops[state.isp].code == Jmp) {
ops[state.isp].code = Nop;
} else if (ops[state.isp].code == Nop) {
ops[state.isp].code = Jmp;
}
return false;
}
auto main(i32 argc, char * argv[]) -> i32 {
auto ops = std::vector<Op>();
{
auto line = std::string();
auto file = std::ifstream("day8.input");
while (getline(file, line)) {
ops.push_back(extract_op(line));
}
}
auto state = State{ 0, 0 };
auto executed = std::vector<bool>(ops.size());
while (!executed[state.isp]) {
executed[state.isp] = true;
execute(state, ops);
}
std::cout << state.acc << std::endl;
state = State{ 0, 0 };
while (state.isp < ops.size()) {
if (attempt_swap(state, ops)) {
std::cout << state.acc << std::endl;
break;
}
execute(state, ops);
}
return 0;
}