Skip to content

Instantly share code, notes, and snippets.

@felix-larsen
Created December 19, 2020 16:15
Show Gist options
  • Save felix-larsen/f1f35600cb56703dcafe35683f8c0d35 to your computer and use it in GitHub Desktop.
Save felix-larsen/f1f35600cb56703dcafe35683f8c0d35 to your computer and use it in GitHub Desktop.
import Foundation
struct Rule {
let condition1: [Int]?
let condition2: [Int]?
let char: Character?
}
let filename = "/Users/felix/xCodeProjects/AdventOfCode2020.playground/Resources/december19.txt"
let contents = try! String(contentsOfFile: filename)
let lines = contents.components(separatedBy: CharacterSet.newlines).filter { !$0.isEmpty}
let rules = lines.filter { $0.contains(":") }.map { line -> (Int, Rule) in
let parts = line.components(separatedBy: ": ")
let ruleNumber = Int(parts[0])!
let rule = parts[1]
var char: Character? = nil
var condition1: [Int]? = nil
var condition2: [Int]? = nil
if rule.contains("\"") {
char = rule[rule.index(rule.startIndex, offsetBy: 1)]
} else if rule.contains("|") {
let rulePair = rule.components(separatedBy: " | ")
let t = rulePair[0].components(separatedBy: " ")
condition1 = t.map { Int($0)! }
condition2 = rulePair[1].components(separatedBy: " ").map { Int($0)! }
} else {
condition1 = rule.components(separatedBy: " ").map { Int($0)! }
}
return (ruleNumber, Rule(condition1: condition1, condition2: condition2, char: char))
}
let rulesDict = Dictionary(uniqueKeysWithValues: rules)
let expressions = lines
.filter { !$0.contains(":") }
.map { line in
ruleMatches([line], ruleNumber: 0, rulesDict: rulesDict)
}
print(expressions)
print(expressions.filter { $0?.contains("") == true }.count)
func ruleMatches(_ exs: [String], ruleNumber: Int, rulesDict: [Int: Rule]) -> [String]? {
let rule = rulesDict[ruleNumber]
if let char = rule?.char {
return exs.compactMap { ex in
if ex.first == char {
return String(ex[ex.index(ex.startIndex, offsetBy: 1)..<ex.endIndex])
} else {
return nil
}
}
}
var condition1Matches = [String]()
if let condition1 = rule?.condition1 {
for ex in exs {
if ex != "" {
var leftovers: [String]? = [ex]
for ruleNumber in condition1 {
if let leftoversNN = leftovers {
leftovers = ruleMatches(leftoversNN, ruleNumber: ruleNumber, rulesDict: rulesDict)
}
}
if let leftoversNN = leftovers {
condition1Matches.append(contentsOf: leftoversNN)
}
}
}
}
var condition2Matches = [String]()
if let condition2 = rule?.condition2 {
for ex in exs {
if ex != "" {
var leftovers: [String]? = [ex]
for ruleNumber in condition2 {
if let leftoversNN = leftovers {
leftovers = ruleMatches(leftoversNN, ruleNumber: ruleNumber, rulesDict: rulesDict)
}
}
if let leftoversNN = leftovers {
condition2Matches.append(contentsOf: leftoversNN)
}
}
}
}
return condition1Matches + condition2Matches
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment