#include "aoc.h" namespace aoc2016 { static int registers[4] = {0, 0, 0, 0}; int& get(int i) { return registers[i]; } // c = a,b,c,d int& get(char c) { return get(c - 'a'); } struct instruction { line_view todo; instruction(line_view l) : todo(l) {} int which() { const char* p = todo.line; switch (*p) { case 'c': return 0; case 'i': return 1; case 'd': return 2; case 'j': return 3; default: break; } return 4; } }; static void get_number(const char** pp, int* d) { const char* p = *pp; int sign = 1; if (*p == '-') { sign = -1; p += 1; } while (*p >= '0' && *p <= '9') { *d = *d * 10 + *p - '0'; p++; } *d *= sign; *pp = p; } typedef void (*todo_f)(size_t*, const char*); void cpy(size_t* i, const char* p) { int d{0}; if (*p >= '0' && *p <= '9') { get_number(&p, &d); p += 1; } else { d = get(*p); p += 2; } get(*p) = d; *i += 1; } void inc(size_t* i, const char* p) { get(*p) += 1; *i += 1; } void dec(size_t* i, const char* p) { get(*p) -= 1; *i += 1; } void jnz(size_t* i, const char* p) { bool condition = *p >= '0' && *p <= '9' ? *p - '0' : get(*p) != 0; if (condition) { p += 2; int offset{0}; get_number(&p, &offset); *i += offset; } else { *i += 1; } } void non(size_t* i, const char* p) { *i += 1; } size_t exec(size_t i, const std::vector& todos) { if (i < todos.size()) { todo_f fs[5] = {cpy, inc, dec, jnz, non}; auto d = todos[i]; // std::cout << d.todo << std::endl; fs[d.which()](&i, d.todo.line + 4); } return i; } std::pair day12(line_view file) { std::vector todos; per_line(file, [&todos](line_view lv) { todos.emplace_back(line_view{lv.line, lv.length - 1}); return true; }); size_t i = 0; while (i < todos.size()) { i = exec(i, todos); } return {registers[0], 0}; } } // namespace aoc2016