107 lines
2.6 KiB
C++
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;
|
|
} |