Files
advent-of-code/2020/puzzle-21-01.cc

107 lines
2.6 KiB
C++

#include <algorithm>
#include <array>
#include <cassert>
#include <iostream>
#include <list>
#include <map>
#include <regex>
#include <set>
#include <string>
#include <tuple>
#include <vector>
using Ingredient = std::string;
using Allergen = std::string;
using Ingredients = std::set<Ingredient>;
using Allergens = std::set<Allergen>;
using IngredientInfo = std::pair<unsigned, Allergens>;
using IngredientMap = std::map<Ingredient, IngredientInfo>;
using AllergenMap = std::map<Allergen, Ingredients>;
class IngredientParser
{
public:
void add_recipe(std::string const& s)
{
auto it = s.begin();
Ingredients i;
while (it != s.end()) {
auto ite = std::find(it, s.end(), ' ');
auto ingredient = std::string(it, ite);
while (ite != s.end() && *ite == ' ') {
++ite;
}
it = ite;
if (ingredient == "(contains") {
break;
}
else {
i.insert(ingredient);
auto [iit, success] = ingredients_.insert({ingredient, {1, Allergens()}});
if (!success) {
iit->second.first++;
}
}
}
while (it != s.end()) {
auto ite = std::find_if(it, s.end(), [](char c) -> bool { return c == ',' || c == ')'; });
auto allergen = std::string(it, ite);
++ite;
while (ite != s.end() && *ite == ' ') {
++ite;
}
it = ite;
auto [insert_it, success] = allergens_.insert({allergen, i});
if (!success) {
Ingredients a;
std::set_intersection(i.begin(), i.end(), insert_it->second.begin(),
insert_it->second.end(), std::inserter(a, a.end()));
insert_it->second = a;
}
}
}
unsigned clean_ingredients()
{
for (auto const& kv : allergens_) {
auto allergen = kv.first;
std::cout << "Allergen " << allergen << ":";
for (auto const& i : kv.second) {
std::cout << " " << i;
auto it = ingredients_.find(i);
assert(it != ingredients_.end());
it->second.second.insert(allergen);
}
std::cout << "\n";
}
unsigned count = 0;
for (auto const& i : ingredients_) {
if (i.second.second.size() == 0) {
std::cout << i.first << " is not an allergen, appears " << i.second.first << ".\n";
count += i.second.first;
}
}
return count;
}
private:
IngredientMap ingredients_;
AllergenMap allergens_;
};
int main(void)
{
std::string line;
IngredientParser parser;
while (std::getline(std::cin, line)) {
parser.add_recipe(line);
}
auto clean = parser.clean_ingredients();
std::cout << "Number of clean ingredients: " << clean << "\n";
return 0;
}