first try for part 2. looks like greedy matching is not possible

This commit is contained in:
Sven Weidauer 2020-12-19 10:13:57 +01:00
parent 8a975abe72
commit 7e8a88629d

View file

@ -4,7 +4,7 @@ let input = loadData(day: 19)
let scanner = Scanner(string: input) let scanner = Scanner(string: input)
scanner.charactersToBeSkipped = .whitespaces scanner.charactersToBeSkipped = .whitespaces
enum Rule { enum Rule: Equatable {
case character(Character) case character(Character)
indirect case sequence(Rule, Rule) indirect case sequence(Rule, Rule)
indirect case alternative(Rule, Rule) indirect case alternative(Rule, Rule)
@ -75,7 +75,7 @@ extension Scanner {
let rules = scanner.parseRuleSet() let rules = scanner.parseRuleSet()
extension Rule { extension Rule {
func matches(rules: RuleSet, _ s: Substring) -> Substring? { func matches(rules: RuleSet, index: Int, _ s: Substring) -> Substring? {
switch self { switch self {
case .character(let ch): case .character(let ch):
if s.first == ch { if s.first == ch {
@ -85,30 +85,38 @@ extension Rule {
return nil return nil
case let .sequence(first, second): case let .sequence(first, second):
if let firstMatch = first.matches(rules: rules, s), let secondMatch = second.matches(rules: rules, firstMatch) { if let firstMatch = first.matches(rules: rules, index: index, s), let secondMatch = second.matches(rules: rules, index: index, firstMatch) {
return secondMatch return secondMatch
} }
return nil return nil
case .alternative(let a, .sequence(let b, .reference(index))) where a == b:
var rest = s
while let match = a.matches(rules: rules, index: index, rest) {
rest = match
}
guard rest != s else { return nil }
return rest
case let .alternative(first, second): case let .alternative(first, second):
if let firstMatch = first.matches(rules: rules, s) { if let firstMatch = first.matches(rules: rules, index: index, s) {
return firstMatch return firstMatch
} }
if let secondMatch = second.matches(rules: rules, s) { if let secondMatch = second.matches(rules: rules, index: index, s) {
return secondMatch return secondMatch
} }
return nil return nil
case .reference(let index): case .reference(let index):
return rules[index]!.matches(rules: rules, s) return rules[index]!.matches(rules: rules, index: index, s)
} }
} }
func matches(rules: RuleSet, _ s: String) -> Bool { func matches(rules: RuleSet, index: Int, _ s: String) -> Bool {
if let result = matches(rules: rules, s[...]), result.isEmpty { if let result = matches(rules: rules, index: index, s[...]), result.isEmpty {
return true return true
} }
@ -138,5 +146,19 @@ extension Scanner {
let messages = scanner.readLines() let messages = scanner.readLines()
print("part 1", messages.lazy.filter { rules[0]!.matches(rules: rules, $0) }.count) print("part 1", messages.lazy.filter { rules[0]!.matches(rules: rules,index: 0, $0) }.count)
let changedRules = """
8: 42 | 42 8
11: 42 31 | 42 11 31
"""
let changeScanner = Scanner(string: changedRules)
changeScanner.charactersToBeSkipped = .whitespaces
let ruleUpdates = changeScanner.parseRuleSet()
let newRules = rules.merging(ruleUpdates) { $1 }
print("part 2", messages.lazy.filter { rules[0]!.matches(rules: newRules, index: 0, $0) }.count)