diff options
author | kaiwu <kaiwu2004@gmail.com> | 2023-01-27 13:01:35 +0800 |
---|---|---|
committer | kaiwu <kaiwu2004@gmail.com> | 2023-01-27 13:01:35 +0800 |
commit | 505fa24b22d0093516ed3d725bec68912e0f878a (patch) | |
tree | cd02fed67a884d7473e58d148b7df4727c8af410 | |
parent | ff62813afc449383b93e80dece1075c9315dbb21 (diff) | |
download | advent-of-code-505fa24b22d0093516ed3d725bec68912e0f878a.tar.gz advent-of-code-505fa24b22d0093516ed3d725bec68912e0f878a.zip |
2016 day23 part1
-rw-r--r-- | src/2016/day12/aoc.cpp | 16 | ||||
-rw-r--r-- | src/2016/day23/README.md | 43 | ||||
-rw-r--r-- | src/2016/day23/aoc.cpp | 117 | ||||
-rw-r--r-- | src/2016/day23/input | 26 | ||||
-rw-r--r-- | test/test_2016.cpp | 2 |
5 files changed, 194 insertions, 10 deletions
diff --git a/src/2016/day12/aoc.cpp b/src/2016/day12/aoc.cpp index bd3a395..2b853ec 100644 --- a/src/2016/day12/aoc.cpp +++ b/src/2016/day12/aoc.cpp @@ -4,9 +4,9 @@ namespace aoc2016 { static int registers[4] = {0, 0, 0, 0}; -int& get(int i) { return registers[i]; } +static int& get(int i) { return registers[i]; } // c = a,b,c,d -int& get(char c) { return get(c - 'a'); } +static int& get(char c) { return get(c - 'a'); } struct instruction { line_view todo; @@ -47,7 +47,7 @@ static void get_number(const char** pp, int* d) { } typedef void (*todo_f)(size_t*, const char*); -void cpy(size_t* i, const char* p) { +static void cpy(size_t* i, const char* p) { int d{0}; if (*p >= '0' && *p <= '9') { get_number(&p, &d); @@ -60,17 +60,17 @@ void cpy(size_t* i, const char* p) { *i += 1; } -void inc(size_t* i, const char* p) { +static void inc(size_t* i, const char* p) { get(*p) += 1; *i += 1; } -void dec(size_t* i, const char* p) { +static void dec(size_t* i, const char* p) { get(*p) -= 1; *i += 1; } -void jnz(size_t* i, const char* p) { +static void jnz(size_t* i, const char* p) { bool condition = *p >= '0' && *p <= '9' ? *p - '0' : get(*p) != 0; if (condition) { p += 2; @@ -82,9 +82,9 @@ void jnz(size_t* i, const char* p) { } } -void non(size_t* i, const char* p) { *i += 1; } +static void non(size_t* i, const char* p) { *i += 1; } -size_t exec(size_t i, const std::vector<instruction>& todos) { +static size_t exec(size_t i, const std::vector<instruction>& todos) { if (i < todos.size()) { todo_f fs[5] = {cpy, inc, dec, jnz, non}; auto d = todos[i]; diff --git a/src/2016/day23/README.md b/src/2016/day23/README.md index e69de29..1423adb 100644 --- a/src/2016/day23/README.md +++ b/src/2016/day23/README.md @@ -0,0 +1,43 @@ +--- Day 23: Safe Cracking --- + +This is one of the top floors of the nicest tower in EBHQ. The Easter Bunny's private office is here, complete with a safe hidden behind a painting, and who wouldn't hide a star in a safe behind a painting? + +The safe has a digital screen and keypad for code entry. A sticky note attached to the safe has a password hint on it: "eggs". The painting is of a large rabbit coloring some eggs. You see 7. + +When you go to type the code, though, nothing appears on the display; instead, the keypad comes apart in your hands, apparently having been smashed. Behind it is some kind of socket - one that matches a connector in your prototype computer! You pull apart the smashed keypad and extract the logic circuit, plug it into your computer, and plug your computer into the safe. + +Now, you just need to figure out what output the keypad would have sent to the safe. You extract the assembunny code from the logic chip (your puzzle input). + +The code looks like it uses almost the same architecture and instruction set that the monorail computer used! You should be able to use the same assembunny interpreter for this as you did there, but with one new instruction: + +tgl x toggles the instruction x away (pointing at instructions like jnz does: positive means forward; negative means backward): + + For one-argument instructions, inc becomes dec, and all other one-argument instructions become inc. + For two-argument instructions, jnz becomes cpy, and all other two-instructions become jnz. + The arguments of a toggled instruction are not affected. + If an attempt is made to toggle an instruction outside the program, nothing happens. + If toggling produces an invalid instruction (like cpy 1 2) and an attempt is later made to execute that instruction, skip it instead. + If tgl toggles itself (for example, if a is 0, tgl a would target itself and become inc a), the resulting instruction is not executed until the next time it is reached. + +For example, given this program: + +cpy 2 a +tgl a +tgl a +tgl a +cpy 1 a +dec a +dec a + + cpy 2 a initializes register a to 2. + The first tgl a toggles an instruction a (2) away from it, which changes the third tgl a into inc a. + The second tgl a also modifies an instruction 2 away from it, which changes the cpy 1 a into jnz 1 a. + The fourth line, which is now inc a, increments a to 3. + Finally, the fifth line, which is now jnz 1 a, jumps a (3) instructions ahead, skipping the dec a instructions. + +In this example, the final value in register a is 3. + +The rest of the electronics seem to place the keypad entry (the number of eggs, 7) in register a, run the code, and then send the value left in register a to the safe. + +What value should be sent to the safe? + diff --git a/src/2016/day23/aoc.cpp b/src/2016/day23/aoc.cpp index 56304eb..9b6a6ba 100644 --- a/src/2016/day23/aoc.cpp +++ b/src/2016/day23/aoc.cpp @@ -2,5 +2,120 @@ namespace aoc2016 { -std::pair<int64_t, int64_t> day23(line_view) { return {0, 0}; } +static int registers[4] = {7, 0, 0, 0}; + +static int& get(int i) { return registers[i]; } +// c = a,b,c,d +static int& get(char c) { return get(c - 'a'); } + +struct instruction23 { + mutable size_t toggles = 0; + line_view todo; + + instruction23(line_view l) : todo(l) {} + + int which() { + std::cout << todo << std::endl; + const char* p = todo.line; + switch (*p) { + case 'c': + return 0; + case 'i': + return 1; + case 'd': + return 2; + case 'j': + return 3; + case 't': + return 4; + 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*, const std::vector<instruction23>&); +static void cpy(size_t* i, const char* p, const std::vector<instruction23>& todos) { + 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; +} + +static void inc(size_t* i, const char* p, const std::vector<instruction23>& todos) { + get(*p) += 1; + *i += 1; +} + +static void dec(size_t* i, const char* p, const std::vector<instruction23>& todos) { + get(*p) -= 1; + *i += 1; +} + +static void jnz(size_t* i, const char* p, const std::vector<instruction23>& todos) { + 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; + } +} + +static void tgl(size_t* i, const char* p, const std::vector<instruction23>& todos) { + size_t next = *i + get(*p); + if (next < todos.size()) { + todos[next].toggles += 1; + } + *i += 1; +} + +static void non(size_t* i, const char* p, const std::vector<instruction23>&) { *i += 1; } + +static size_t exec(size_t i, const std::vector<instruction23>& todos) { + if (i < todos.size()) { + todo_f fs[6] = {cpy, inc, dec, jnz, tgl, non}; + auto d = todos[i]; + fs[d.which()](&i, d.todo.line + 4, todos); + } + return i; +} + +std::pair<int64_t, int64_t> day23(line_view file) { + std::vector<instruction23> 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 {0, 0}; +} } // namespace aoc2016 diff --git a/src/2016/day23/input b/src/2016/day23/input index e69de29..3ff0460 100644 --- a/src/2016/day23/input +++ b/src/2016/day23/input @@ -0,0 +1,26 @@ +cpy a b +dec b +cpy a d +cpy 0 a +cpy b c +inc a +dec c +jnz c -2 +dec d +jnz d -5 +dec b +cpy b c +cpy c d +dec d +inc c +jnz d -2 +tgl c +cpy -16 c +jnz 1 c +cpy 90 c +jnz 90 d +inc a +inc d +jnz d -2 +inc c +jnz c -5 diff --git a/test/test_2016.cpp b/test/test_2016.cpp index 2e62ccb..5fa17e7 100644 --- a/test/test_2016.cpp +++ b/test/test_2016.cpp @@ -204,7 +204,7 @@ TEST_CASE("Grid Computing", "[2016]") { } -TEST_CASE("", "[2016]") { +TEST_CASE("Safe Cracking", "[2016]") { line_view lv = load_file("../src/2016/day23/input"); auto p = aoc2016::day23(lv); REQUIRE(0 == p.first); |