Files
advent-of-code/2015/puzzle-15-01.cc

125 lines
2.9 KiB
C++

#include <cassert>
#include <cctype>
#include <climits>
#include <functional>
#include <iostream>
#include <map>
#include <regex>
#include <set>
#include <string>
#include <variant>
using Score = long;
using PropertyMap = std::map<std::string, Score>;
struct Ingredient
{
explicit Ingredient(std::string const& s)
{
auto colon = s.find(':');
name_ = s.substr(0, colon);
auto suffix = s.substr(colon + 1);
std::cout << name_ << "\n";
while (!suffix.empty()) {
static const std::regex re(",? (\\w+) (-?\\d+)");
std::smatch m;
if (std::regex_search(suffix, m, re)) {
auto [it, success] = properties_.insert({m.str(1), std::stol(m.str(2))});
assert(success);
std::cout << " " << it->first << ": " << it->second << "\n";
suffix = m.suffix();
}
else {
assert(false);
}
}
}
bool operator<(Ingredient const& rhs) const noexcept { return name_ < rhs.name_; }
std::string const& name() const noexcept { return name_; }
void update_score(Score amount, PropertyMap& totals) const
{
for (auto const& kv : properties_) {
if (kv.first == "calories") {
continue;
}
auto [it, success] = totals.insert({kv.first, amount * kv.second});
if (!success) {
it->second += amount * kv.second;
}
}
}
private:
std::string name_;
PropertyMap properties_;
};
struct Ingredients
{
void add_ingredient(std::string const& s) { ingredients_.push_back(Ingredient(s)); }
Score best_combination(Score amount) const
{
PropertyMap totals;
return best_combination(amount, ingredients_.begin(), 0UL, totals);
}
private:
Score best_combination(Score amount, std::vector<Ingredient>::const_iterator it, Score best_score,
PropertyMap& totals) const
{
it->update_score(amount, totals);
auto it2 = it;
++it2;
if (it2 == ingredients_.end()) {
auto score = calculate_score(totals);
best_score = std::max(best_score, score);
it->update_score(-amount, totals);
return best_score;
}
for (auto allocation = amount - 1; allocation > 0; --allocation) {
it->update_score(-1, totals);
best_score =
std::max(best_score, best_combination(amount - allocation, it2, best_score, totals));
}
it->update_score(-1, totals);
return best_score;
}
Score calculate_score(PropertyMap const& totals) const
{
Score r = 1;
for (auto const& kv : totals) {
if (kv.first == "calories") {
continue;
}
if (kv.second < 0) {
return 0;
}
r *= kv.second;
}
return r;
}
std::vector<Ingredient> ingredients_;
};
int main(int argc, char** argv)
{
Ingredients ingredients;
std::string line;
while (std::getline(std::cin, line)) {
ingredients.add_ingredient(line);
}
auto r = ingredients.best_combination(100);
std::cout << "Solution: " << r << "\n";
return 0;
}