first try for part 2. looks like greedy matching is not possible
This commit is contained in:
parent
8a975abe72
commit
7e8a88629d
1 changed files with 31 additions and 9 deletions
|
@ -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)
|
||||||
|
|
Loading…
Add table
Reference in a new issue