2021-12-14 16:24:15 +00:00
|
|
|
//
|
|
|
|
// File.swift
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Created by Max Nuding on 14.12.21.
|
|
|
|
//
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import Runner
|
|
|
|
|
2021-12-14 19:13:34 +00:00
|
|
|
struct Pair: Hashable {
|
|
|
|
let first: String.Element
|
|
|
|
let second: String.Element
|
2021-12-14 16:24:15 +00:00
|
|
|
|
2021-12-14 19:13:34 +00:00
|
|
|
init(_ str: String) {
|
|
|
|
first = str.first!
|
|
|
|
second = str.last!
|
2021-12-14 16:24:15 +00:00
|
|
|
}
|
|
|
|
|
2021-12-14 19:13:34 +00:00
|
|
|
init(first: String.Element, second: String.Element) {
|
|
|
|
self.first = first
|
|
|
|
self.second = second
|
|
|
|
}
|
2021-12-14 16:24:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class Day14: Runnable {
|
|
|
|
let inputPath: String
|
|
|
|
|
|
|
|
required init(inputPath: String) {
|
|
|
|
self.inputPath = inputPath
|
|
|
|
}
|
|
|
|
|
|
|
|
public func run() {
|
|
|
|
let input = try! String(contentsOfFile: inputPath)
|
|
|
|
let parts = input
|
|
|
|
.trimmingCharacters(in: .newlines)
|
|
|
|
.components(separatedBy: "\n\n")
|
2021-12-14 18:50:38 +00:00
|
|
|
let startingPolymer = parts.first!
|
2021-12-14 16:24:15 +00:00
|
|
|
let replacements = parts.last!
|
|
|
|
.components(separatedBy: .newlines)
|
2021-12-14 18:50:38 +00:00
|
|
|
.map {$0.components(separatedBy: " -> ")}
|
2021-12-14 19:13:34 +00:00
|
|
|
.reduce(into: [Pair:String.Element](), {
|
|
|
|
$0[Pair($1.first!)] = $1.last!.first!
|
2021-12-14 18:50:38 +00:00
|
|
|
})
|
2021-12-14 16:24:15 +00:00
|
|
|
|
2021-12-14 19:13:34 +00:00
|
|
|
var pairCounts = [Pair:Int]()
|
2021-12-14 18:50:38 +00:00
|
|
|
for i in startingPolymer.indices {
|
|
|
|
let next = startingPolymer.index(i, offsetBy: 1)
|
|
|
|
guard next != startingPolymer.endIndex else {
|
|
|
|
continue
|
2021-12-14 16:24:15 +00:00
|
|
|
}
|
2021-12-14 19:13:34 +00:00
|
|
|
pairCounts[Pair(first: startingPolymer[i], second: startingPolymer[next]), default: 0] += 1
|
2021-12-14 16:24:15 +00:00
|
|
|
}
|
2021-12-14 18:50:38 +00:00
|
|
|
var charCount = startingPolymer.reduce(into: [String.Element:Int](), {
|
2021-12-14 16:24:15 +00:00
|
|
|
$0[$1, default: 0] += 1
|
|
|
|
})
|
2021-12-14 18:50:38 +00:00
|
|
|
|
|
|
|
for step in 1...40 {
|
|
|
|
let tmpPairCounts = pairCounts
|
2021-12-14 19:13:34 +00:00
|
|
|
|
2021-12-14 18:50:38 +00:00
|
|
|
for pairCount in tmpPairCounts {
|
|
|
|
let pair = pairCount.key
|
|
|
|
let replacement = replacements[pair]!
|
|
|
|
pairCounts[pair]! -= pairCount.value
|
2021-12-14 19:13:34 +00:00
|
|
|
pairCounts[Pair(first: pair.first, second: replacement), default: 0] += pairCount.value
|
|
|
|
pairCounts[Pair(first: replacement, second: pair.second), default: 0] += pairCount.value
|
|
|
|
charCount[replacement, default: 0] += pairCount.value
|
2021-12-14 18:50:38 +00:00
|
|
|
}
|
|
|
|
if step == 10 {
|
|
|
|
printResult(charCount: charCount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printResult(charCount: charCount)
|
|
|
|
}
|
|
|
|
|
|
|
|
func printResult(charCount: [String.Element:Int]) {
|
2021-12-14 19:13:34 +00:00
|
|
|
// Sort instead of min/max so we need to only go through the dict once
|
|
|
|
let sorted = charCount.sorted(by: {$0.value > $1.value })
|
|
|
|
let maxC = sorted.first!
|
|
|
|
let minC = sorted.last!
|
2021-12-14 16:24:15 +00:00
|
|
|
print(maxC.value - minC.value)
|
|
|
|
}
|
|
|
|
}
|