-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathday_15b.cpp
164 lines (147 loc) · 4.46 KB
/
day_15b.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <algorithm>
#include <cmath>
#include <fstream>
#include <ostream>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
int calculate_hash(const std::string& line) {
int value = 0;
for (const auto c : line) {
value += int(c);
value *= 17;
value %= 256;
}
return value;
}
struct Instruction {
std::string label;
char op;
int focal_length;
int box;
};
Instruction parse_substr(const std::string substr) {
std::size_t idx = substr.find_first_of("-=");
Instruction p;
p.label = substr.substr(0, idx);
p.op = substr[idx];
if (p.op == '=') p.focal_length = std::stoi(substr.substr(idx + 1, substr.size() - idx - 1));
return p;
}
std::vector<Instruction> parse(const std::string& s) {
std::vector<Instruction> instructions;
std::size_t start = 0;
std::size_t end = s.find(',', start);
while (end != std::string::npos) {
instructions.push_back(parse_substr(s.substr(start, end - start)));
start = end + 1;
end = s.find(',', start);
}
instructions.push_back(parse_substr(s.substr(start, s.size() - start)));
return instructions;
}
struct LensInBox {
std::string label;
int focal_length;
std::string next_lens_label;
std::string previous_lens_label;
friend std::ostream& operator << (std::ostream& os, const LensInBox& lens);
};
std::ostream& operator << (std::ostream& os, const LensInBox& lens) {
os << "[" << lens.label << ' ' << lens.focal_length << ']'; // << ',' <<lens.next_lens_label << ',' << lens.previous_lens_label << "}";
return os;
}
struct Box {
int id;
std::unordered_map<std::string, LensInBox> lenses;
std::string first = "";
std::string last = "";
friend std::ostream& operator << (std::ostream& os, const Box& box);
void remove_lens(const std::string& label) {
if (auto it = lenses.find(label); it != lenses.end()) {
if (it->second.next_lens_label != "") {
lenses[it->second.next_lens_label].previous_lens_label = it->second.previous_lens_label;
}
if (it->second.previous_lens_label != "") {
lenses[it->second.previous_lens_label].next_lens_label = it->second.next_lens_label;
}
if (first == label) {
first = it->second.next_lens_label;
}
if (last == label) {
last = it->second.previous_lens_label;
}
lenses.erase(it);
}
}
void add_lens(const std::string& label, const int focal_length) {
auto it = lenses.find(label);
if (it == lenses.end()) {
if (first == "") first = label;
LensInBox lens;
lens.label = label;
lens.focal_length = focal_length;
lens.next_lens_label = "";
lens.previous_lens_label = last;
lenses[last].next_lens_label = label;
last = label;
lenses[label] = lens;
return;
}
it->second.focal_length = focal_length;
}
};
std::ostream& operator << (std::ostream& os, const Box& box) {
os << box.id << ": ";
auto current = box.first;
while (current != "") {
const auto& lens = box.lenses.at(current);
os << lens << ' ';
current = lens.next_lens_label;
}
return os;
}
int main(int argc, char * argv[]) {
std::string input = "../input/day_15_input";
if (argc > 1) {
input = argv[1];
}
std::string line;
std::fstream file(input);
std::getline(file, line);
const auto instructions = parse(line);
std::unordered_map<int, Box> boxes;
for (auto& instruction : instructions) {
// std::cout << instruction.label << '\n';
const auto box_id = calculate_hash(instruction.label);
if (instruction.op == '=') {
if (boxes.find(box_id) == boxes.end()) boxes[box_id].id = box_id;
boxes[box_id].add_lens(instruction.label, instruction.focal_length);
} else if (instruction.op == '-') {
boxes[box_id].remove_lens(instruction.label);
} else {
std::cout << "This should not happen" << '\n';
std::cout << '|' << instruction.op << '|' << '\n';
}
// for (const auto& [id, box] : boxes) {
// std::cout << box << '\n';
// }
}
// std::cout << "-------------------" << '\n';
std::size_t total = 0;
for (const auto [id, box] : boxes) {
auto current = box.first;
int slot = 1;
while (current != "") {
const auto& lens = box.lenses.at(current);
// const auto temp = (id + 1) * slot * lens.focal_length;
// std::cout << lens << ": " << temp << '\n';
total += (id + 1) * slot * lens.focal_length;
slot++;
current = lens.next_lens_label;
}
}
std::cout << total << '\n';
return 0;
}