#include #include #include #include #include #include #include #include "util.h" using Lens = std::pair; using Box = std::vector; using Boxes = std::array; 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> parse(const char* file) { using namespace util::separators; std::vector> 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(label)); } else { int focal = std::stoi( std::string{ str.substr(c + 1) } ); cmds.push_back(std::make_unique(label, focal)); } }; util::accumulate(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; }