Convert day 19 part 1 to use regular expressions
parent
ae8847bdd1
commit
196a679dc3
106
day19/day19.cpp
106
day19/day19.cpp
|
@ -1,3 +1,4 @@
|
||||||
|
#include <folly/Format.h>
|
||||||
#include <folly/String.h>
|
#include <folly/String.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -7,6 +8,7 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -92,76 +94,66 @@ MultiGrammarEntry parseSinglePattern(const std::string &rawPattern) {
|
||||||
return patternComponents;
|
return patternComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<int, AlternatableMultiGrammarEntry> parseGrammar(const std::vector<std::string> &patterns) {
|
std::unordered_multimap<int, MultiGrammarEntry> parseGrammar(const std::vector<std::string> &patterns) {
|
||||||
std::unordered_map<int, AlternatableMultiGrammarEntry> grammar;
|
std::unordered_multimap<int, MultiGrammarEntry> grammar;
|
||||||
std::transform(
|
for (const std::string &patternLine : patterns) {
|
||||||
patterns.cbegin(), patterns.cend(), std::inserter(grammar, grammar.end()), [](const std::string &patternLine) {
|
auto colonIndex = patternLine.find(":");
|
||||||
auto colonIndex = patternLine.find(":");
|
std::string rawIndex = patternLine.substr(0, colonIndex);
|
||||||
std::string rawIndex = patternLine.substr(0, colonIndex);
|
int patternIndex = std::stoi(rawIndex);
|
||||||
int patternIndex = std::stoi(rawIndex);
|
std::vector<std::string> rawAlternations;
|
||||||
std::vector<std::string> rawAlternations;
|
// An extra +1 on the colon index to get rid of the space after the colon
|
||||||
// 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);
|
||||||
folly::split(ALTERNATING_DELIM, patternLine.substr(colonIndex + 2), rawAlternations);
|
|
||||||
|
|
||||||
AlternatableMultiGrammarEntry entries;
|
std::transform(
|
||||||
std::transform(
|
rawAlternations.cbegin(),
|
||||||
rawAlternations.cbegin(), rawAlternations.cend(), std::back_inserter(entries), parseSinglePattern);
|
rawAlternations.cend(),
|
||||||
|
std::inserter(grammar, grammar.end()),
|
||||||
return std::pair<int, AlternatableMultiGrammarEntry>(patternIndex, entries);
|
[patternIndex](const std::string &pattern) {
|
||||||
});
|
return std::make_pair(patternIndex, parseSinglePattern(pattern));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return grammar;
|
return grammar;
|
||||||
}
|
}
|
||||||
|
|
||||||
int matchesHowManyChars(
|
std::string convertToRegularExpression(const std::unordered_multimap<int, MultiGrammarEntry> &grammar, int rule) {
|
||||||
const std::unordered_map<int, AlternatableMultiGrammarEntry> &grammar, const std::string_view toParse, int rule = 0,
|
std::vector<std::string> expressions;
|
||||||
int depth = 0) {
|
auto ruleIterators = grammar.equal_range(rule);
|
||||||
auto indentation = std::string(depth, '|');
|
std::transform(
|
||||||
std::cout << indentation << "Working on " << toParse << std::endl;
|
ruleIterators.first,
|
||||||
AlternatableMultiGrammarEntry ruleAlternations = grammar.at(rule);
|
ruleIterators.second,
|
||||||
std::optional<std::pair<MultiGrammarEntry, int>> best;
|
std::back_inserter(expressions),
|
||||||
for (const MultiGrammarEntry &alternation : ruleAlternations) {
|
[&grammar](const std::pair<int, MultiGrammarEntry> &entry) {
|
||||||
int numMatched = 0;
|
MultiGrammarEntry alternative = entry.second;
|
||||||
int i = 0;
|
std::string expression;
|
||||||
for (auto entryIt = alternation.cbegin(); entryIt != alternation.cend(); (++entryIt, i++)) {
|
for (const GrammarEntry &grammarEntry : alternative) {
|
||||||
GrammarEntry entry = *entryIt;
|
if (grammarEntry.isLookup()) {
|
||||||
int ruleMatchCount;
|
expression += convertToRegularExpression(grammar, grammarEntry.getIndex());
|
||||||
if (entry.isLookup()) {
|
} else {
|
||||||
std::cout << indentation << "Checking rule " << entry.getIndex() << std::endl;
|
expression += grammarEntry.getValue();
|
||||||
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::cout << indentation << "Result: " << numMatched << std::endl;
|
return expression;
|
||||||
|
});
|
||||||
|
|
||||||
if (!ruleMatchCount) {
|
if (expressions.size() == 1) {
|
||||||
break;
|
return expressions.at(0);
|
||||||
}
|
} else {
|
||||||
|
return folly::format("({})", folly::join("|", expressions)).str();
|
||||||
numMatched += ruleMatchCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << indentation << "Full result: " << numMatched << std::endl;
|
|
||||||
if (!best || numMatched > best->second) {
|
|
||||||
best = std::pair<MultiGrammarEntry, int>(alternation, numMatched);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!best) {
|
std::regex convertToRegularExpression(const std::unordered_multimap<int, MultiGrammarEntry> &grammar) {
|
||||||
return 0;
|
auto rawRegularExpression = convertToRegularExpression(grammar, 0);
|
||||||
}
|
return std::regex(rawRegularExpression);
|
||||||
|
|
||||||
return best->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int part1(const std::vector<std::string> &patterns, const std::vector<std::string> &testStrings) {
|
int part1(const std::vector<std::string> &patterns, const std::vector<std::string> &testStrings) {
|
||||||
std::unordered_map<int, AlternatableMultiGrammarEntry> grammar = parseGrammar(patterns);
|
std::unordered_multimap<int, MultiGrammarEntry> grammar = parseGrammar(patterns);
|
||||||
return std::count_if(testStrings.cbegin(), testStrings.cend(), [&grammar](const std::string &testString) {
|
std::regex inputRegex = convertToRegularExpression(grammar);
|
||||||
return matchesHowManyChars(grammar, testString) == testString.length();
|
return std::count_if(testStrings.cbegin(), testStrings.cend(), [&inputRegex](const std::string &testString) {
|
||||||
|
return std::regex_match(testString, inputRegex);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue