This commit is contained in:
Sven Weidauer 2020-12-14 19:02:48 +01:00
parent db394f7e14
commit 1caa6bda84

View file

@ -1,15 +1,39 @@
import Foundation import Foundation
let scanner = Scanner(string: loadData(day: 14)) let input = loadData(day: 14)
class Problem {
let scanner: Scanner
/// Each bit where the mask is "1" is set here
var maskBits: UInt64 = 0
/// Each bit where the mask is "X" is set here
var maskUsed: UInt64 = 0
var mem: [UInt64:UInt64] = [:]
var writeMem: (Problem, UInt64, UInt64) -> Void
init(_ input: String, writeMem: @escaping (Problem, UInt64, UInt64) -> Void) {
scanner = Scanner(string: input)
self.writeMem = writeMem
}
func run() {
while !scanner.isAtEnd {
if scanner.string("mask = "), let mask = scanner.scanCharacters(from: Self.maskSet) {
readMask(mask)
} else if scanner.string("mem["), let addr = scanner.scanUInt64(), scanner.string("] = "), let value = scanner.scanUInt64() {
writeMem(self, addr, value)
} else {
assertionFailure("Invalid input")
}
}
var maskBits: UInt64 = 0 print("sum", mem.values.reduce(0, +))
var maskUsed: UInt64 = 0 }
private func readMask(_ mask: String) {
var mem: [UInt64:UInt64] = [:]
func readMask(_ mask: String) {
assert(mask.count == 36) assert(mask.count == 36)
maskBits = 0 maskBits = 0
@ -26,31 +50,19 @@ func readMask(_ mask: String) {
default: assertionFailure("Invalid character in mask") default: assertionFailure("Invalid character in mask")
} }
} }
}
func applyMask(_ value: UInt64) -> UInt64 {
(value & maskUsed) | maskBits
}
let maskSet = CharacterSet(charactersIn: "01X")
/*
while !scanner.isAtEnd {
if scanner.string("mask = "), let mask = scanner.scanCharacters(from: maskSet) {
readMask(mask)
} else if scanner.string("mem["), let addr = scanner.scanInt(), scanner.string("] = "), let value = scanner.scanUInt64() {
mem[addr] = applyMask(value)
} else {
assertionFailure("Invalid input")
} }
static private let maskSet = CharacterSet(charactersIn: "01X")
} }
*/
func printPadded(_ val: UInt64) {
let s = String(val, radix: 2) let part1 = Problem(input) { problem, addr, value in
print(String(repeating: " ", count: 36 - s.count) + s) problem.mem[addr] = (value & problem.maskUsed) | problem.maskBits
} }
part1.run()
func possibleValues(_ mask: UInt64) -> [UInt64] { func possibleValues(_ mask: UInt64) -> [UInt64] {
var values: [UInt64] = [] var values: [UInt64] = []
@ -71,22 +83,11 @@ func possibleValues(_ mask: UInt64) -> [UInt64] {
return values return values
} }
func writeMem(_ addr: UInt64, _ value: UInt64) { let part2 = Problem(input) { problem, addr, value in
for i in possibleValues(maskUsed) { for i in possibleValues(problem.maskUsed) {
let effective = i | ((addr | maskBits) & ~maskUsed) let effective = i | ((addr | problem.maskBits) & ~problem.maskUsed)
mem[effective] = value problem.mem[effective] = value
} }
} }
while !scanner.isAtEnd { part2.run()
if scanner.string("mask = "), let mask = scanner.scanCharacters(from: maskSet) {
readMask(mask)
} else if scanner.string("mem["), let addr = scanner.scanUInt64(), scanner.string("] = "), let value = scanner.scanUInt64() {
writeMem(addr, value)
} else {
assertionFailure("Invalid input")
}
}
print("sum", mem.values.reduce(0, +))