diff options
author | Federico Igne <undyamon@disroot.org> | 2023-12-15 18:20:56 +0100 |
---|---|---|
committer | Federico Igne <undyamon@disroot.org> | 2023-12-15 18:20:56 +0100 |
commit | eafa46252f2d41a86bf218b8af0460eeb5818eb9 (patch) | |
tree | 24a286059ba947b24b7b57c5a5e7c26980d029e8 /2023/15/src/part2.cpp | |
parent | fd2077171f5b0b1a9f3bb4224865f0d5c84c21ae (diff) | |
download | aoc-eafa46252f2d41a86bf218b8af0460eeb5818eb9.tar.gz aoc-eafa46252f2d41a86bf218b8af0460eeb5818eb9.zip |
aoc(2315): Lens Library
Diffstat (limited to '2023/15/src/part2.cpp')
-rw-r--r-- | 2023/15/src/part2.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/2023/15/src/part2.cpp b/2023/15/src/part2.cpp new file mode 100644 index 0000000..4758e86 --- /dev/null +++ b/2023/15/src/part2.cpp | |||
@@ -0,0 +1,136 @@ | |||
1 | #include <algorithm> | ||
2 | #include <iostream> | ||
3 | #include <memory> | ||
4 | #include <fstream> | ||
5 | #include <vector> | ||
6 | #include <array> | ||
7 | #include <tuple> | ||
8 | |||
9 | #include "util.h" | ||
10 | |||
11 | using Lens = std::pair<std::string,int>; | ||
12 | using Box = std::vector<Lens>; | ||
13 | using Boxes = std::array<Box,256>; | ||
14 | |||
15 | struct Cmd | ||
16 | { | ||
17 | protected: | ||
18 | |||
19 | int boxi_; | ||
20 | std::string label_; | ||
21 | |||
22 | public: | ||
23 | |||
24 | Cmd(const std::string& label) : boxi_{ hash(label) }, label_{label} | ||
25 | { | ||
26 | } | ||
27 | |||
28 | virtual void apply(Boxes& boxes) const | ||
29 | { | ||
30 | auto& box = boxes[boxi_]; | ||
31 | auto has_same_label = [this](const auto& lens) { return lens.first == label_; }; | ||
32 | |||
33 | if (auto lens = std::find_if(box.cbegin(), box.cend(), has_same_label); | ||
34 | lens != box.cend()) | ||
35 | { | ||
36 | box.erase(lens); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | static int hash(const std::string& label) | ||
41 | { | ||
42 | int hash{}; | ||
43 | for (unsigned char c : label) | ||
44 | { | ||
45 | hash += c; | ||
46 | hash *= 17; | ||
47 | hash %= 256; | ||
48 | } | ||
49 | return hash; | ||
50 | } | ||
51 | }; | ||
52 | |||
53 | class Add : public Cmd | ||
54 | { | ||
55 | int focal_; | ||
56 | |||
57 | public: | ||
58 | |||
59 | Add(const std::string& label, int focal) : Cmd(label), focal_{ focal } | ||
60 | { | ||
61 | } | ||
62 | |||
63 | void apply(Boxes& boxes) const override | ||
64 | { | ||
65 | auto& box = boxes[boxi_]; | ||
66 | auto has_same_label = [this](const auto& lens) { return lens.first == label_; }; | ||
67 | |||
68 | if (auto lens = std::find_if(box.begin(), box.end(), has_same_label); | ||
69 | lens != box.end()) | ||
70 | { | ||
71 | lens->second = focal_; | ||
72 | } | ||
73 | else | ||
74 | { | ||
75 | box.push_back({ label_, focal_ }); | ||
76 | } | ||
77 | } | ||
78 | }; | ||
79 | |||
80 | int power(const Boxes& boxes) | ||
81 | { | ||
82 | int power{}; | ||
83 | for (int b = 0; b < boxes.size(); ++b) | ||
84 | { | ||
85 | for(int l = 0; l < boxes[b].size(); ++l) | ||
86 | { | ||
87 | power += (b + 1) * (l + 1) * boxes[b][l].second; | ||
88 | } | ||
89 | } | ||
90 | return power; | ||
91 | } | ||
92 | |||
93 | std::vector<std::unique_ptr<Cmd>> parse(const char* file) | ||
94 | { | ||
95 | using namespace util::separators; | ||
96 | |||
97 | std::vector<std::unique_ptr<Cmd>> cmds; | ||
98 | |||
99 | if (std::ifstream input{ file }; input.is_open()) | ||
100 | { | ||
101 | std::string line; | ||
102 | std::getline(input,line); | ||
103 | std::string_view view{ line }; | ||
104 | |||
105 | auto to_cmd = [&cmds](std::string_view& str) | ||
106 | { | ||
107 | auto c{ str.find_first_of("=-") }; | ||
108 | std::string label{ str.substr(0, c) }; | ||
109 | if (str[c] == '-') | ||
110 | { | ||
111 | cmds.push_back(std::make_unique<Cmd>(label)); | ||
112 | } | ||
113 | else | ||
114 | { | ||
115 | int focal = std::stoi( std::string{ str.substr(c + 1) } ); | ||
116 | cmds.push_back(std::make_unique<Add>(label, focal)); | ||
117 | } | ||
118 | }; | ||
119 | |||
120 | util::accumulate<COMMA>(view, to_cmd); | ||
121 | } | ||
122 | |||
123 | return cmds; | ||
124 | } | ||
125 | |||
126 | int main(int argc, char* argv[]) | ||
127 | { | ||
128 | Boxes boxes; | ||
129 | for (const auto& cmd : parse(argv[1])) | ||
130 | { | ||
131 | cmd->apply(boxes); | ||
132 | } | ||
133 | |||
134 | std::cout << power(boxes) << std::endl; | ||
135 | return 0; | ||
136 | } | ||