Clean up day 21 part 2

master
Nick Krichevsky 2020-12-25 13:52:28 -05:00
parent fcdc3cbd30
commit bc2d06aabe
2 changed files with 58 additions and 17 deletions

15
day21/Makefile Normal file
View File

@ -0,0 +1,15 @@
CC=g++
BIN_NAME=day21
CCFLAGS=-o $(BIN_NAME) -g -std=c++17
LDFLAGS=-lfolly
.PHONY: all, clean
all: $(BIN_NAME)
clean:
rm -f $(BIN_NAME)
$(BIN_NAME): day21.cpp
$(CC) $(CCFLAGS) $(LDFLAGS) day21.cpp

View File

@ -10,6 +10,7 @@
#include <string>
#include <vector>
// Pair of ingredients and allergens
using IngredientLineItem = std::pair<std::vector<std::string>, std::vector<std::string>>;
auto constexpr INGREDIENT_PATTERN = R"((.*) \(contains (.*)\))";
@ -24,6 +25,11 @@ std::vector<std::string> readInput(const std::string &filename) {
return input;
}
/**
* Split an input line into its components of both the foreign ingredient and the allergens
* @param inputLine The input line
* @return std::pair<std::string, std::string> The ingredients and allergens as a pair
*/
std::pair<std::string, std::string> splitInputLine(const std::string &inputLine) {
std::regex pattern(INGREDIENT_PATTERN);
std::smatch matches;
@ -34,6 +40,11 @@ std::pair<std::string, std::string> splitInputLine(const std::string &inputLine)
return std::make_pair(matches[1].str(), matches[2].str());
}
/**
* Parse the puzzle input
* @param input The puzzle input
* @return std::vector<IngredientLineItem> The line items for the ingredients
*/
std::vector<IngredientLineItem> parseInput(const std::vector<std::string> &input) {
std::vector<IngredientLineItem> res;
std::transform(input.cbegin(), input.cend(), std::back_inserter(res), [](const std::string &inputLine) {
@ -49,6 +60,11 @@ std::vector<IngredientLineItem> parseInput(const std::vector<std::string> &input
return res;
}
/**
* Correlate ingredients to their all
* @param input The parsed puzzle input
* @return std::map<std::string, std::set<std::string>> A map of allergens to their possible ingredients (not concrete)
*/
std::map<std::string, std::set<std::string>> correlateIngredients(const std::vector<IngredientLineItem> &input) {
std::map<std::string, std::set<std::string>> knownCorrelations;
std::vector<std::string> allIngredients;
@ -76,6 +92,31 @@ std::map<std::string, std::set<std::string>> correlateIngredients(const std::vec
return knownCorrelations;
}
/**
* Given a map of the known allergen mappings, generate the canonical name
* @param mappedIngredients The mapped ingredients
* @return std::string The canonical name of the food
*/
std::string generateCanonicalName(const std::map<std::string, std::string> &mappedIngredients) {
std::vector<std::string> sortedAllergens;
std::transform(
mappedIngredients.cbegin(),
mappedIngredients.cend(),
std::back_inserter(sortedAllergens),
[](const auto &entry) { return entry.first; });
std::sort(sortedAllergens.begin(), sortedAllergens.end());
std::vector<std::string> finalNameComponents;
std::transform(
sortedAllergens.cbegin(),
sortedAllergens.cend(),
std::back_inserter(finalNameComponents),
[&mappedIngredients](const std::string &allergenName) { return mappedIngredients.at(allergenName); });
return folly::join(",", finalNameComponents);
}
int part1(const std::vector<IngredientLineItem> &input) {
auto knownCorrelations = correlateIngredients(input);
std::set<std::string> foundIngredients;
@ -131,6 +172,7 @@ std::string part2(const std::vector<IngredientLineItem> &input) {
correlationSet = knownCorrelations.at(*allergenName);
}
if (toVisit.empty() || (correlationSet->get().size() > lastSize && !toRevisit.empty())) {
// priority_queue does not provide a ranged insert - do this by hand.
std::for_each(toRevisit.begin(), toRevisit.end(), [&toVisit](const std::string set) { toVisit.push(set); });
toRevisit.clear();
continue;
@ -159,23 +201,7 @@ std::string part2(const std::vector<IngredientLineItem> &input) {
}
}
std::vector<std::string> sortedAllergens;
std::transform(
mappedIngredients.cbegin(),
mappedIngredients.cend(),
std::back_inserter(sortedAllergens),
[](const auto &entry) { return entry.first; });
std::sort(sortedAllergens.begin(), sortedAllergens.end());
std::vector<std::string> finalNameComponents;
std::transform(
sortedAllergens.cbegin(),
sortedAllergens.cend(),
std::back_inserter(finalNameComponents),
[&mappedIngredients](const std::string &allergenName) { return mappedIngredients.at(allergenName); });
return folly::join(",", finalNameComponents);
return generateCanonicalName(mappedIngredients);
}
int main(int argc, char *argv[]) {