1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#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<instruction>& 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<int64_t, int64_t> day12(line_view file) {
std::vector<instruction> 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
|