-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathday_16b.cpp
137 lines (127 loc) · 4.12 KB
/
day_16b.cpp
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 <algorithm>
#include <fstream>
#include <iostream>
#include <numeric>
#include <string>
#include <unordered_map>
#include <vector>
struct Packet {
int version;
int type;
long long value; // when type != 4, value is set to -1, as contains subpackets
std::vector<Packet> sub_ps; // when type == 4, there will be no subpackets
Packet (const int version, const int type, const long long value, const std::vector<Packet>& sub_ps) :
version(version), type(type), value(value), sub_ps(sub_ps) {};
};
std::string convert_to_binary(const std::string& s) {
std::unordered_map<char, std::string> m {
{'0', "0000"},
{'1', "0001"},
{'2', "0010"},
{'3', "0011"},
{'4', "0100"},
{'5', "0101"},
{'6', "0110"},
{'7', "0111"},
{'8', "1000"},
{'9', "1001"},
{'A', "1010"},
{'B', "1011"},
{'C', "1100"},
{'D', "1101"},
{'E', "1110"},
{'F', "1111"}
};
std::string r;
for (const char c : s) {
r += m[c];
}
return r;
}
long long convert_to_decimal(const std::string& s) {
long long i = 0;
for (const char c : s) {
i = i * 2 + (c - '0');
}
return i;
}
long long calculate_packet_value(Packet& p) {
if (p.value == -1) { // when type != 4, value is set to -1, as contains subpackets
for (auto& sub_p : p.sub_ps) { // update the values of each subpacket
calculate_packet_value(sub_p);
}
if (p.type == 0) {
p.value = std::accumulate(std::begin(p.sub_ps), std::end(p.sub_ps), 0ll, [](const auto sum, const auto& sub_p) { return sum + sub_p.value; });
} else if (p.type == 1) {
p.value = std::accumulate(std::begin(p.sub_ps), std::end(p.sub_ps), 1ll, [](const auto sum, const auto& sub_p) { return sum * sub_p.value; });
} else if (p.type == 2) {
p.value = std::min_element(std::begin(p.sub_ps), std::end(p.sub_ps), [](const auto& p1, const auto& p2) { return p1.value < p2.value; })->value;
} else if (p.type == 3) {
p.value = std::max_element(std::begin(p.sub_ps), std::end(p.sub_ps), [](const auto& p1, const auto& p2) { return p1.value < p2.value; })->value;
} else if (p.type == 5) {
p.value = p.sub_ps[0].value > p.sub_ps[1].value ? 1 : 0;
} else if (p.type == 6) {
p.value = p.sub_ps[0].value < p.sub_ps[1].value ? 1 : 0;
} else if (p.type == 7) {
p.value = p.sub_ps[0].value == p.sub_ps[1].value ? 1 : 0;
}
}
return p.value;
}
Packet convert_to_packet(const std::string& s, size_t& index) {
const int version = convert_to_decimal(s.substr(index, 3));
index += 3;
const int type = convert_to_decimal(s.substr(index, 3));
index += 3;
if (type == 4) {
std::string bin_num;
while (index < s.size()) {
if (s[index] == '1') {
bin_num += s.substr(index + 1, 4);
index += 5;
} else if (s[index] == '0') {
bin_num += s.substr(index + 1, 4);
index += 5;
break;
}
}
return Packet(version, type, convert_to_decimal(bin_num), std::vector<Packet>());
} else {
const int length_id = convert_to_decimal(s.substr(index, 1));
index += 1;
if (length_id == 0) {
const auto l_bits = convert_to_decimal(s.substr(index, 15));
index += 15;
const auto init_index = index;
auto p = Packet(version, type, -1, std::vector<Packet>());
while (index < init_index + l_bits) {
p.sub_ps.emplace_back(convert_to_packet(s, index));
}
return p;
} else if (length_id == 1) {
const auto n_sub_ps = convert_to_decimal(s.substr(index, 11));
index += 11;
auto p = Packet(version, type, -1, std::vector<Packet>());
for (int i = 0; i < n_sub_ps; i++) {
p.sub_ps.emplace_back(convert_to_packet(s, index));
}
return p;
}
}
return Packet(0, 0 , 0, {});
}
int main(int argc, char * argv[]) {
std::string input = "../input/day_16_input";
if (argc > 1) {
input = argv[1];
}
std::string line;
std::fstream file(input);
std::vector<std::vector<int>> map;
std::getline(file, line);
const auto b = convert_to_binary(line);
size_t index = 0;
auto p = convert_to_packet(b, index);
std::cout << calculate_packet_value(p) << '\n';
return 0;
}