2021-12-14 22:33:06 +01:00
|
|
|
@main
|
2021-12-15 19:35:04 +01:00
|
|
|
struct Day14: Puzzle {
|
2021-12-14 22:33:06 +01:00
|
|
|
mutating func run() {
|
|
|
|
let part1 = calculate(start, depth: 10)
|
|
|
|
print("Part 1:", part1.values.max()! - part1.values.min()!)
|
|
|
|
|
|
|
|
let part2 = calculate(start, depth: 40)
|
|
|
|
print("Part 2:", part2.values.max()! - part2.values.min()!)
|
|
|
|
}
|
|
|
|
|
|
|
|
mutating func calculate(_ string: String, depth: Int) -> [Character: Int] {
|
|
|
|
var result: [Character: Int] = [:]
|
|
|
|
for (a, b) in zip(string, string.dropFirst()) {
|
|
|
|
result.merge(calculate(a, b, depth: depth), uniquingKeysWith: +)
|
|
|
|
}
|
|
|
|
result[string.last!, default: 0] += 1
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
struct CacheKey: Hashable {
|
|
|
|
var string: String
|
|
|
|
var depth: Int
|
|
|
|
}
|
|
|
|
var cache: [CacheKey: [Character: Int]] = [:]
|
|
|
|
|
|
|
|
mutating func calculate(_ first: Character, _ second: Character, depth: Int) -> [Character: Int] {
|
|
|
|
guard depth > 0 else {
|
|
|
|
return [first: 1]
|
|
|
|
}
|
|
|
|
|
|
|
|
let pair = "\(first)\(second)"
|
|
|
|
let cacheKey = CacheKey(string: pair, depth: depth)
|
|
|
|
|
|
|
|
if let result = cache[cacheKey] {
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
let mid = mapping[pair]!
|
|
|
|
|
|
|
|
var result = calculate(first, mid, depth: depth - 1)
|
|
|
|
result.merge(calculate(mid, second, depth: depth - 1), uniquingKeysWith: +)
|
|
|
|
|
|
|
|
cache[cacheKey] = result
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
let start = "KBKPHKHHNBCVCHPSPNHF"
|
|
|
|
let mapping: [String: Character] = [
|
|
|
|
"OP": "H",
|
|
|
|
"CF": "C",
|
|
|
|
"BB": "V",
|
|
|
|
"KH": "O",
|
|
|
|
"CV": "S",
|
|
|
|
"FV": "O",
|
|
|
|
"FS": "K",
|
|
|
|
"KO": "C",
|
|
|
|
"PP": "S",
|
|
|
|
"SH": "K",
|
|
|
|
"FH": "O",
|
|
|
|
"NF": "H",
|
|
|
|
"PN": "P",
|
|
|
|
"BO": "H",
|
|
|
|
"OK": "K",
|
|
|
|
"PO": "P",
|
|
|
|
"SF": "K",
|
|
|
|
"BF": "P",
|
|
|
|
"HH": "S",
|
|
|
|
"KP": "H",
|
|
|
|
"HB": "N",
|
|
|
|
"NP": "V",
|
|
|
|
"KK": "P",
|
|
|
|
"PF": "P",
|
|
|
|
"BK": "V",
|
|
|
|
"OF": "H",
|
|
|
|
"FO": "S",
|
|
|
|
"VC": "P",
|
|
|
|
"FK": "B",
|
|
|
|
"NK": "S",
|
|
|
|
"CB": "B",
|
|
|
|
"PV": "C",
|
|
|
|
"CO": "N",
|
|
|
|
"BN": "C",
|
|
|
|
"HV": "H",
|
|
|
|
"OC": "N",
|
|
|
|
"NB": "O",
|
|
|
|
"CS": "S",
|
|
|
|
"HK": "C",
|
|
|
|
"VS": "F",
|
|
|
|
"BH": "C",
|
|
|
|
"PC": "S",
|
|
|
|
"KC": "O",
|
|
|
|
"VO": "P",
|
|
|
|
"FB": "K",
|
|
|
|
"BV": "V",
|
|
|
|
"VN": "N",
|
|
|
|
"ON": "F",
|
|
|
|
"VH": "H",
|
|
|
|
"CN": "O",
|
|
|
|
"HO": "O",
|
|
|
|
"SV": "O",
|
|
|
|
"SS": "H",
|
|
|
|
"KF": "N",
|
|
|
|
"SP": "C",
|
|
|
|
"NS": "V",
|
|
|
|
"SO": "F",
|
|
|
|
"BC": "P",
|
|
|
|
"HC": "C",
|
|
|
|
"FP": "H",
|
|
|
|
"OH": "S",
|
|
|
|
"OB": "S",
|
|
|
|
"HF": "V",
|
|
|
|
"SC": "B",
|
|
|
|
"SN": "N",
|
|
|
|
"VK": "C",
|
|
|
|
"NC": "V",
|
|
|
|
"VV": "S",
|
|
|
|
"SK": "K",
|
|
|
|
"PK": "K",
|
|
|
|
"PS": "N",
|
|
|
|
"KB": "S",
|
|
|
|
"KS": "C",
|
|
|
|
"NN": "C",
|
|
|
|
"OO": "C",
|
|
|
|
"BS": "B",
|
|
|
|
"NV": "H",
|
|
|
|
"FF": "P",
|
|
|
|
"FC": "N",
|
|
|
|
"OS": "H",
|
|
|
|
"KN": "N",
|
|
|
|
"VP": "B",
|
|
|
|
"PH": "N",
|
|
|
|
"NH": "S",
|
|
|
|
"OV": "O",
|
|
|
|
"FN": "V",
|
|
|
|
"CP": "B",
|
|
|
|
"NO": "V",
|
|
|
|
"CK": "C",
|
|
|
|
"VF": "B",
|
|
|
|
"HS": "B",
|
|
|
|
"KV": "K",
|
|
|
|
"VB": "H",
|
|
|
|
"SB": "S",
|
|
|
|
"BP": "S",
|
|
|
|
"CC": "F",
|
|
|
|
"HP": "B",
|
|
|
|
"PB": "P",
|
|
|
|
"HN": "P",
|
|
|
|
"CH": "O",
|
|
|
|
]
|
|
|
|
}
|