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
138
139
140
|
#include "aoc.h"
#include <map>
namespace aoc2016 {
static std::map<int, bot*> bots = {};
static std::map<int, bot*> outputs = {};
static bot* get(int i, std::map<int, bot*>& bs) {
auto p = bs.insert({i, nullptr});
if (p.second) {
bot* b = new bot;
b->idx = i;
p.first->second = b;
}
return p.first->second;
}
typedef bot* (*get_method)(int);
bot* get_bot(int i) { return get(i, bots); }
bot* get_output(int i) { return get(i, outputs); }
static void get_number(const char** pp, int* d) {
const char* p = *pp;
while (*p >= '0' && *p <= '9') {
*d = *d * 10 + *p - '0';
p++;
}
*pp = p;
}
void parse_three(const char* p) {
int is[3] = {0, 0, 0};
int i{0};
get_method gets[2] = {get_bot, get_bot};
while (true) {
if (*p >= '0' && *p <= '9') {
if (i == 1 || i == 2) {
if (*(p - 3) == 'u') {
gets[i - 1] = get_output;
}
// if (*(p - 3) == 'o') {
// gets[i - 1] = get_bot;
// }
}
get_number(&p, is + i);
i++;
}
if (*p == '\n')
break;
p++;
}
bot* b0 = get_bot(is[0]);
bot* b1 = gets[0](is[1]);
b1->is_output = gets[0] == get_output;
bot* b2 = gets[1](is[2]);
b2->is_output = gets[1] == get_output;
b0->outputs[0] = b1;
b0->outputs[1] = b2;
// const char* ds[2] = {"bot", "output"};
// printf("%d %d[%s] %d[%s]\n", b0->idx, b1->idx, ds[(int)b1->is_output], b2->idx, ds[(int)b2->is_output]);
}
void parse_two(const char* p) {
int is[2] = {0, 0};
int i{0};
while (true) {
if (*p >= '0' && *p <= '9') {
get_number(&p, is + i);
i++;
}
if (*p == '\n')
break;
p++;
}
get_bot(is[1])->set(is[0]);
}
void give(bot* b0, bot* b1, int v, int i) {
if (b1 != nullptr) {
// const char* ds[2] = {"bot", "output"};
// printf("%d give %d[%s] value %d\n", b0->idx, b1->idx, ds[(int)b1->is_output], v);
if (b1->is_output) {
b1->get(v);
} else {
b1->set(v);
}
b0->vs[i] = 0;
}
}
int64_t robot_work(int l, int h, int* idx) {
while (true) {
size_t n{0};
for (auto& kv : bots) {
bot* b = kv.second;
if (b->can_give()) {
n += 1;
int l0 = b->vs[0];
int h0 = b->vs[1];
if (l0 == l && h0 == h) {
*idx = b->idx;
}
give(b, b->outputs[0], l0, 0);
give(b, b->outputs[1], h0, 1);
}
}
if (n == 0)
break;
}
int64_t v{1};
for (int i = 0; i < 3; i++) {
v *= get_output(i)->values[0];
}
return v;
}
void print(int x, bot* b) {
printf("\noutput %d\n", x);
for (auto i : b->values) {
printf("%d ", i);
}
}
std::pair<int64_t, int64_t> day10(line_view file) {
per_line(file, [](line_view lv) {
const char* p = lv.line;
if (*p == 'b') {
parse_three(p);
}
if (*p == 'v') {
parse_two(p);
}
return true;
});
int idx{INT32_MAX};
auto o = robot_work(17, 61, &idx);
return {idx, o};
}
} // namespace aoc2016
|