From f6ed34b9f9faf2a5cf7c40cbb291f00841f7a095 Mon Sep 17 00:00:00 2001 From: Nick Krichevsky Date: Mon, 21 Dec 2020 17:37:50 -0500 Subject: [PATCH] Add solution to day 19 --- day19/day19.cpp | 104 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 87 insertions(+), 17 deletions(-) diff --git a/day19/day19.cpp b/day19/day19.cpp index d612415..2199307 100644 --- a/day19/day19.cpp +++ b/day19/day19.cpp @@ -12,6 +12,7 @@ #include #include +constexpr auto RULE_DELIM = ":"; constexpr auto ALTERNATING_DELIM = " | "; class GrammarEntry; using MultiGrammarEntry = std::vector; @@ -97,7 +98,7 @@ MultiGrammarEntry parseSinglePattern(const std::string &rawPattern) { std::unordered_multimap parseGrammar(const std::vector &patterns) { std::unordered_multimap grammar; for (const std::string &patternLine : patterns) { - auto colonIndex = patternLine.find(":"); + auto colonIndex = patternLine.find(RULE_DELIM); std::string rawIndex = patternLine.substr(0, colonIndex); int patternIndex = std::stoi(rawIndex); std::vector rawAlternations; @@ -119,41 +120,109 @@ std::unordered_multimap parseGrammar(const std::vector &grammar, int rule) { std::vector expressions; auto ruleIterators = grammar.equal_range(rule); + std::vector> entries(ruleIterators.first, ruleIterators.second); + for (const auto &entry : entries) { + auto cycleIt = std::find_if(entry.second.cbegin(), entry.second.cend(), [rule](const GrammarEntry &ruleEntry) { + return ruleEntry.isLookup() && ruleEntry.getIndex() == rule; + }); + + if (cycleIt != entry.second.cend()) { + entries = std::vector>{entry}; + break; + } + } std::transform( - ruleIterators.first, - ruleIterators.second, + entries.cbegin(), + entries.cend(), std::back_inserter(expressions), - [&grammar](const std::pair &entry) { + [&grammar, rule](const std::pair &entry) { MultiGrammarEntry alternative = entry.second; + std::string prefix; std::string expression; + std::string suffixPrefix; + std::string suffix; + bool isNonRegularCycle = false; for (const GrammarEntry &grammarEntry : alternative) { - if (grammarEntry.isLookup()) { - expression += convertToRegularExpression(grammar, grammarEntry.getIndex()); - } else { + if (!grammarEntry.isLookup()) { expression += grammarEntry.getValue(); + } else if ( + grammarEntry.getIndex() == rule && alternative.back().isLookup() && + rule == alternative.back().getIndex()) { + expression = folly::format("(?:{})+?", expression).str(); + } else if (grammarEntry.getIndex() == rule) { + isNonRegularCycle = true; + // This grossness will be resolved when using a format string. We want to be able to replace this + // with a number later. + suffixPrefix = folly::format("((?:{}){{{{{{}}}}}})((?:", expression).str(); + expression.clear(); + suffix = "){{{}}})"; + } else { + expression += convertToRegularExpression(grammar, grammarEntry.getIndex()); } } - return expression; + if (!isNonRegularCycle) { + return expression; + } else { + std::vector fullSuffixElements; + for (int i = 1; i < 8; i++) { + fullSuffixElements.push_back( + folly::format(suffixPrefix, i).str() + expression + folly::format(suffix, i).str()); + } + std::cout << prefix << std::endl; + + return prefix + "(" + folly::join("|", fullSuffixElements) + ")"; + } }); if (expressions.size() == 1) { return expressions.at(0); } else { - return folly::format("({})", folly::join("|", expressions)).str(); + return folly::format("(?:{})", folly::join("|", expressions)).str(); } } -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_multimap grammar = parseGrammar(patterns); - std::regex inputRegex = convertToRegularExpression(grammar); + std::regex inputRegex = std::regex(convertToRegularExpression(grammar, 0)); return std::count_if(testStrings.cbegin(), testStrings.cend(), [&inputRegex](const std::string &testString) { - return std::regex_match(testString, inputRegex); + std::smatch matches; + if (std::regex_match(testString, matches, inputRegex)) { + std::cerr << testString << std::endl; + return true; + } + + return false; + }); +} + +int part2(const std::vector &patterns, const std::vector &testStrings) { + std::unordered_multimap grammar = parseGrammar(patterns); + grammar.erase(8); + grammar.erase(11); + grammar.emplace(8, MultiGrammarEntry{GrammarEntry(42)}); + grammar.emplace(8, MultiGrammarEntry{GrammarEntry(42), GrammarEntry(8)}); + grammar.emplace(11, MultiGrammarEntry{GrammarEntry(42), GrammarEntry(31)}); + grammar.emplace(11, MultiGrammarEntry{GrammarEntry(42), GrammarEntry(11), GrammarEntry(31)}); + std::regex inputRegex(convertToRegularExpression(grammar, 0)); + std::regex rule42Regex(convertToRegularExpression(grammar, 42)); + std::regex rule31Regex(convertToRegularExpression(grammar, 31)); + std::cout << "Expressions" << std::endl; + std::cout << "0" << std::endl; + std::cout << convertToRegularExpression(grammar, 0) << std::endl; + std::cout << "42" << std::endl; + std::cout << convertToRegularExpression(grammar, 42) << std::endl; + std::cout << "31" << std::endl; + std::cout << convertToRegularExpression(grammar, 31) << std::endl; + + return std::count_if(testStrings.cbegin(), testStrings.cend(), [&inputRegex](const std::string &testString) { + std::smatch matches; + if (std::regex_match(testString, matches, inputRegex)) { + std::cerr << testString << std::endl; + return true; + } + + return false; }); } @@ -166,5 +235,6 @@ int main(int argc, char *argv[]) { auto input = readInput(argv[1]); auto parsedInput = splitInput(input); - std::cout << part1(parsedInput.first, parsedInput.second) << std::endl; + // std::cout << part1(parsedInput.first, parsedInput.second) << std::endl; + std::cout << part2(parsedInput.first, parsedInput.second) << std::endl; }