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
|
#include <algorithm>
#include <iostream>
#include <memory>
#include <fstream>
#include <vector>
#include <array>
#include <tuple>
#include "util.h"
using Lens = std::pair<std::string,int>;
using Box = std::vector<Lens>;
using Boxes = std::array<Box,256>;
struct Cmd
{
protected:
int boxi_;
std::string label_;
public:
Cmd(const std::string& label) : boxi_{ hash(label) }, label_{label}
{
}
virtual void apply(Boxes& boxes) const
{
auto& box = boxes[boxi_];
auto has_same_label = [this](const auto& lens) { return lens.first == label_; };
if (auto lens = std::find_if(box.cbegin(), box.cend(), has_same_label);
lens != box.cend())
{
box.erase(lens);
}
}
static int hash(const std::string& label)
{
int hash{};
for (unsigned char c : label)
{
hash += c;
hash *= 17;
hash %= 256;
}
return hash;
}
};
class Add : public Cmd
{
int focal_;
public:
Add(const std::string& label, int focal) : Cmd(label), focal_{ focal }
{
}
void apply(Boxes& boxes) const override
{
auto& box = boxes[boxi_];
auto has_same_label = [this](const auto& lens) { return lens.first == label_; };
if (auto lens = std::find_if(box.begin(), box.end(), has_same_label);
lens != box.end())
{
lens->second = focal_;
}
else
{
box.push_back({ label_, focal_ });
}
}
};
int power(const Boxes& boxes)
{
int power{};
for (int b = 0; b < boxes.size(); ++b)
{
for(int l = 0; l < boxes[b].size(); ++l)
{
power += (b + 1) * (l + 1) * boxes[b][l].second;
}
}
return power;
}
std::vector<std::unique_ptr<Cmd>> parse(const char* file)
{
using namespace util::separators;
std::vector<std::unique_ptr<Cmd>> cmds;
if (std::ifstream input{ file }; input.is_open())
{
std::string line;
std::getline(input,line);
std::string_view view{ line };
auto to_cmd = [&cmds](std::string_view& str)
{
auto c{ str.find_first_of("=-") };
std::string label{ str.substr(0, c) };
if (str[c] == '-')
{
cmds.push_back(std::make_unique<Cmd>(label));
}
else
{
int focal = std::stoi( std::string{ str.substr(c + 1) } );
cmds.push_back(std::make_unique<Add>(label, focal));
}
};
util::accumulate<COMMA>(view, to_cmd);
}
return cmds;
}
int main(int argc, char* argv[])
{
Boxes boxes;
for (const auto& cmd : parse(argv[1]))
{
cmd->apply(boxes);
}
std::cout << power(boxes) << std::endl;
return 0;
}
|