diff options
Diffstat (limited to 'src/2017')
-rw-r--r-- | src/2017/day23/README.md | 11 | ||||
-rw-r--r-- | src/2017/day23/aoc.cpp | 101 |
2 files changed, 111 insertions, 1 deletions
diff --git a/src/2017/day23/README.md b/src/2017/day23/README.md index 34f9caf..0afb1af 100644 --- a/src/2017/day23/README.md +++ b/src/2017/day23/README.md @@ -13,3 +13,14 @@ The coprocessor is currently set to some kind of debug mode, which allows for te If you run the program (your puzzle input), how many times is the mul instruction invoked? +--- Part Two --- +Now, it's time to fix the problem. + +The debug mode switch is wired directly to register a. You flip the switch, which makes register a now start at 1 when the program is executed. + +Immediately, the coprocessor begins to overheat. Whoever wrote this program obviously didn't choose a very efficient implementation. You'll need to optimize the program if it has any hope of completing before Santa needs that printer working. + +The coprocessor's ultimate goal is to determine the final value left in register h once the program completes. Technically, if it had that... it wouldn't even need to run the program. + +After setting register a to 1, if the program were to run to completion, what value would be left in register h? + diff --git a/src/2017/day23/aoc.cpp b/src/2017/day23/aoc.cpp index 444cec9..7d990e3 100644 --- a/src/2017/day23/aoc.cpp +++ b/src/2017/day23/aoc.cpp @@ -2,5 +2,104 @@ namespace aoc2017 { -std::pair<int64_t, int64_t> day23(line_view) { return {0, 0}; } +static int64_t& get(char x, int64_t rs[26]) { return rs[x - 'a']; } +static void get_number(const char** pp, int64_t* d) { + const char* p = *pp; + int sign = 1; + if (*p == '-') { + sign = -1; + p++; + } + while (*p >= '0' && *p <= '9') { + *d = *d * 10 + *p - '0'; + p++; + } + *d *= sign; + *pp = p; +} + +static int64_t get_number(const char* p, int64_t rs[26]) { + int64_t d{0}; + if (*p == '-' || (*p >= '0' && (*p <= '9'))) { + get_number(&p, &d); + } else { + d = get(*p, rs); + } + return d; +} + +typedef void (*f23)(size_t* i, const char* p1, const char* p2, int64_t rs[26]); + +static void set(size_t* i, const char* p1, const char* p2, int64_t rs[26]) { + get(*p1, rs) = get_number(p2, rs); + *i += 1; +} + +static void sub(size_t* i, const char* p1, const char* p2, int64_t rs[26]) { + get(*p1, rs) -= get_number(p2, rs); + *i += 1; +} + +static void mul(size_t* i, const char* p1, const char* p2, int64_t rs[26]) { + get(*p1, rs) *= get_number(p2, rs); + *i += 1; +} + +static void jnz(size_t* i, const char* p1, const char* p2, int64_t rs[26]) { + auto d1 = get_number(p1, rs); + auto d2 = get_number(p2, rs); + *i += d1 != 0 ? d2 : 1; +} + +static struct { + f23 f; + const char* s; + int c; +} fs[4] = {{set, "set", 0}, {sub, "sub", 0}, {mul, "mul", 0}, {jnz, "jnz", 0}}; + +static size_t exec(size_t index, const std::vector<line_view>& todos, int64_t rs[26]) { + if (index < todos.size()) { + auto& todo = todos[index]; + const char* p = todo.line; + auto match = [](const char* p, const char* p0) -> bool { + for (int i = 0; i < 3; i++) { + if (*(p + i) != *(p0 + i)) { + return false; + } + } + return true; + }; + + for (auto& fx : fs) { + if (match(p, fx.s)) { + fx.c += 1; + fx.f(&index, p + 4, p + 6, rs); + break; + } + } + } + return index; +} + +static void part1(const std::vector<line_view>& todos) { + size_t index{0}; + int64_t rs[26] = {0}; + + while (index < todos.size()) { + index = exec(index, todos, rs); + } +} + +std::pair<int64_t, int64_t> day23(line_view file) { + std::vector<line_view> todos; + per_line(file, [&todos](line_view lv) { + todos.push_back(lv); + return true; + }); + + part1(todos); + int64_t t0 = fs[2].c; + + return {t0, 0}; +} } // namespace aoc2017 |