From bc2d06aabe3a4438f9eeaaa99cafdea11bc54b05 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Fri, 25 Dec 2020 13:52:28 -0500 Subject: [PATCH] Clean up day 21 part 2 --- day21/Makefile | 15 +++++++++++++ day21/day21.cpp | 60 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 day21/Makefile diff --git a/day21/Makefile b/day21/Makefile new file mode 100644 index 0000000..fb6478a --- /dev/null +++ b/day21/Makefile @@ -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 + diff --git a/day21/day21.cpp b/day21/day21.cpp index a5665c2..8b1e54f 100644 --- a/day21/day21.cpp +++ b/day21/day21.cpp @@ -10,6 +10,7 @@ #include #include +// Pair of ingredients and allergens using IngredientLineItem = std::pair, std::vector>; auto constexpr INGREDIENT_PATTERN = R"((.*) \(contains (.*)\))"; @@ -24,6 +25,11 @@ std::vector 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 The ingredients and allergens as a pair + */ std::pair splitInputLine(const std::string &inputLine) { std::regex pattern(INGREDIENT_PATTERN); std::smatch matches; @@ -34,6 +40,11 @@ std::pair 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 The line items for the ingredients + */ std::vector parseInput(const std::vector &input) { std::vector res; std::transform(input.cbegin(), input.cend(), std::back_inserter(res), [](const std::string &inputLine) { @@ -49,6 +60,11 @@ std::vector parseInput(const std::vector &input return res; } +/** + * Correlate ingredients to their all + * @param input The parsed puzzle input + * @return std::map> A map of allergens to their possible ingredients (not concrete) + */ std::map> correlateIngredients(const std::vector &input) { std::map> knownCorrelations; std::vector allIngredients; @@ -76,6 +92,31 @@ std::map> 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 &mappedIngredients) { + std::vector 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 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 &input) { auto knownCorrelations = correlateIngredients(input); std::set foundIngredients; @@ -131,6 +172,7 @@ std::string part2(const std::vector &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 &input) { } } - std::vector 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 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[]) {