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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include "aoc.h"
namespace aoc2019 {
static int* input = nullptr;
static int input_sequence = 0;
static void get_number(const char** pp, int* 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;
}
// 0001
// 0101
// 1001
// 1101
static int mode(int x, int* m1, int* m2) {
int m{0}, m0{0};
int* is[] = {&m, &m0, m1, m2};
int i{0};
while (x > 0) {
*is[i++] = x % 10;
x /= 10;
}
return m;
}
static int& get(std::vector<int>& codes, int mode, int i) { return mode == 0 ? codes[codes[i]] : codes[i]; }
static size_t opt1(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
get(codes, 0, i + 3) = get(codes, m1, i + 1) + get(codes, m2, i + 2);
return i + 4;
}
static size_t opt2(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
get(codes, 0, i + 3) = get(codes, m1, i + 1) * get(codes, m2, i + 2);
return i + 4;
}
static size_t opt3(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
get(codes, 0, i + 1) = *(input + input_sequence++);
return i + 2;
}
static size_t opt4(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
outputs.push_back(get(codes, m1, i + 1));
return i + 2;
}
static size_t opt5(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
size_t x = i + 3;
if (get(codes, m1, i + 1) != 0) {
x = get(codes, m2, i + 2);
}
return x;
}
static size_t opt6(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
size_t x = i + 3;
if (get(codes, m1, i + 1) == 0) {
x = get(codes, m2, i + 2);
}
return x;
}
static size_t opt7(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
get(codes, 0, i + 3) = int(get(codes, m1, i + 1) < get(codes, m2, i + 2));
return i + 4;
}
static size_t opt8(std::vector<int>& codes, std::vector<int>& outputs, size_t i, int m1, int m2) {
get(codes, 0, i + 3) = int(get(codes, m1, i + 1) == get(codes, m2, i + 2));
return i + 4;
}
typedef size_t (*opt_f)(std::vector<int>&, std::vector<int>&, size_t, int, int);
static void run(size_t i, std::vector<int>& codes, std::vector<int>& outputs, interrupt_f f, void* p) {
// printf("execute %d at %zu\n", codes[i], i);
static opt_f opts[] = {opt1, opt2, opt3, opt4, opt5, opt6, opt7, opt8};
if (codes[i] != 99) {
int m1{0}, m2{0};
int m = mode(codes[i], &m1, &m2);
int x = opts[m - 1](codes, outputs, i, m1, m2);
bool stop = f != nullptr && f(x, outputs, p);
if (!stop) {
run(x, codes, outputs, f, p);
}
}
}
static int run(int i, const std::vector<int>& codes) {
int is[] = {i};
set_computer(is);
return run_computer(codes);
}
void set_computer(int* i) {
input = i;
input_sequence = 0;
}
int run_computer(std::vector<int> codes) {
std::vector<int> outputs;
run(0, codes, outputs, nullptr, nullptr);
return outputs[outputs.size() - 1];
}
void run_computer(size_t i, std::vector<int>& codes, std::vector<int>& outputs, interrupt_f f, void* p) {
run(i, codes, outputs, f, p);
}
std::pair<int, int> day5(line_view file) {
const char* p = file.line;
std::vector<int> optcodes;
while (p < file.line + file.length) {
if ((*p >= '0' && *p <= '9') || *p == '-') {
int d{0};
get_number(&p, &d);
optcodes.push_back(d);
}
p++;
}
return {run(1, optcodes), run(5, optcodes)};
}
} // namespace aoc2019
|