From 196a679dc3887dcd3a9fdab922afdbd3d8c89005 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Sun, 20 Dec 2020 23:16:59 -0500 Subject: [PATCH] Convert day 19 part 1 to use regular expressions --- day19/day19.cpp | 106 ++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/day19/day19.cpp b/day19/day19.cpp index 587e099..d612415 100644 --- a/day19/day19.cpp +++ b/day19/day19.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -7,6 +8,7 @@ #include #include #include +#include #include #include @@ -92,76 +94,66 @@ MultiGrammarEntry parseSinglePattern(const std::string &rawPattern) { return patternComponents; } -std::unordered_map parseGrammar(const std::vector &patterns) { - std::unordered_map grammar; - std::transform( - patterns.cbegin(), patterns.cend(), std::inserter(grammar, grammar.end()), [](const std::string &patternLine) { - auto colonIndex = patternLine.find(":"); - std::string rawIndex = patternLine.substr(0, colonIndex); - int patternIndex = std::stoi(rawIndex); - std::vector rawAlternations; - // An extra +1 on the colon index to get rid of the space after the colon - folly::split(ALTERNATING_DELIM, patternLine.substr(colonIndex + 2), rawAlternations); +std::unordered_multimap parseGrammar(const std::vector &patterns) { + std::unordered_multimap grammar; + for (const std::string &patternLine : patterns) { + auto colonIndex = patternLine.find(":"); + std::string rawIndex = patternLine.substr(0, colonIndex); + int patternIndex = std::stoi(rawIndex); + std::vector rawAlternations; + // An extra +1 on the colon index to get rid of the space after the colon + folly::split(ALTERNATING_DELIM, patternLine.substr(colonIndex + 2), rawAlternations); - AlternatableMultiGrammarEntry entries; - std::transform( - rawAlternations.cbegin(), rawAlternations.cend(), std::back_inserter(entries), parseSinglePattern); - - return std::pair(patternIndex, entries); - }); + std::transform( + rawAlternations.cbegin(), + rawAlternations.cend(), + std::inserter(grammar, grammar.end()), + [patternIndex](const std::string &pattern) { + return std::make_pair(patternIndex, parseSinglePattern(pattern)); + }); + } return grammar; } -int matchesHowManyChars( - const std::unordered_map &grammar, const std::string_view toParse, int rule = 0, - int depth = 0) { - auto indentation = std::string(depth, '|'); - std::cout << indentation << "Working on " << toParse << std::endl; - AlternatableMultiGrammarEntry ruleAlternations = grammar.at(rule); - std::optional> best; - for (const MultiGrammarEntry &alternation : ruleAlternations) { - int numMatched = 0; - int i = 0; - for (auto entryIt = alternation.cbegin(); entryIt != alternation.cend(); (++entryIt, i++)) { - GrammarEntry entry = *entryIt; - int ruleMatchCount; - if (entry.isLookup()) { - std::cout << indentation << "Checking rule " << entry.getIndex() << std::endl; - ruleMatchCount = matchesHowManyChars(grammar, toParse.substr(numMatched), entry.getIndex(), depth + 1); - } else { - std::cout << indentation << "Checking rule " << entry.getValue() << std::endl; - char toMatch = toParse.at(i); - char ruleValue = entry.getValue(); - ruleMatchCount = (toMatch == ruleValue); +std::string convertToRegularExpression(const std::unordered_multimap &grammar, int rule) { + std::vector expressions; + auto ruleIterators = grammar.equal_range(rule); + std::transform( + ruleIterators.first, + ruleIterators.second, + std::back_inserter(expressions), + [&grammar](const std::pair &entry) { + MultiGrammarEntry alternative = entry.second; + std::string expression; + for (const GrammarEntry &grammarEntry : alternative) { + if (grammarEntry.isLookup()) { + expression += convertToRegularExpression(grammar, grammarEntry.getIndex()); + } else { + expression += grammarEntry.getValue(); + } } - std::cout << indentation << "Result: " << numMatched << std::endl; + return expression; + }); - if (!ruleMatchCount) { - break; - } - - numMatched += ruleMatchCount; - } - - std::cout << indentation << "Full result: " << numMatched << std::endl; - if (!best || numMatched > best->second) { - best = std::pair(alternation, numMatched); - } + if (expressions.size() == 1) { + return expressions.at(0); + } else { + return folly::format("({})", folly::join("|", expressions)).str(); } +} - if (!best) { - return 0; - } - - return best->second; +std::regex convertToRegularExpression(const std::unordered_multimap &grammar) { + auto rawRegularExpression = convertToRegularExpression(grammar, 0); + return std::regex(rawRegularExpression); } int part1(const std::vector &patterns, const std::vector &testStrings) { - std::unordered_map grammar = parseGrammar(patterns); - return std::count_if(testStrings.cbegin(), testStrings.cend(), [&grammar](const std::string &testString) { - return matchesHowManyChars(grammar, testString) == testString.length(); + std::unordered_multimap grammar = parseGrammar(patterns); + std::regex inputRegex = convertToRegularExpression(grammar); + return std::count_if(testStrings.cbegin(), testStrings.cend(), [&inputRegex](const std::string &testString) { + return std::regex_match(testString, inputRegex); }); }