This commit is contained in:
Max Nuding 2021-12-03 21:50:50 +01:00
parent 8072d84a5a
commit b0609897df
Signed by: phlaym
GPG Key ID: A06651BAB6777237

View File

@ -16,15 +16,15 @@ struct Day03 {
let commands = input
.components(separatedBy: .newlines)
.filter { !$0.isEmpty }
//.compactMap { MoveCommand(line: $0) }
runA(commands)
//runB(commands)
runB(commands)
}
func runA(_ commands: [String]) {
let neededForMajority = commands.count / 2
let lastBitIndex = commands.first!.count
var countsOnes = [Int](repeating: 0, count: lastBitIndex)
// There's probably some clever bitwise operation to solve this
for command in commands {
let m = command.map { Bool.init(digit: $0)! }.map { $0 ? 1 : 0 }
countsOnes.enumerated().forEach { (idx, elem) in
@ -42,11 +42,81 @@ struct Day03 {
}
return (gamma, episolon)
})
print(dec.episolon * dec.gamma)<
print(dec.episolon * dec.gamma)
}
func runB(_ commands: [String]) {
// Incredibly naive, iterates through the list many, many times
// Still runs plenty fast (~70ms on my machine)
// Too tired to optimize this
let lastBitIndex = commands.first!.count
var countsOnes = [Int](repeating: 0, count: lastBitIndex)
for command in commands {
let m = command.map { Bool.init(digit: $0)! }.map { $0 ? 1 : 0 }
countsOnes.enumerated().forEach { (idx, elem) in
countsOnes[idx] += m[idx]
}
}
var oxygenCommands = commands
var scrubberCommands = commands
for pos in 0..<lastBitIndex {
var countsOnesOxygen = [Int](repeating: 0, count: lastBitIndex)
for command in oxygenCommands {
let m = command.map { Bool.init(digit: $0)! }.map { $0 ? 1 : 0 }
countsOnesOxygen.enumerated().forEach { (idx, elem) in
countsOnesOxygen[idx] += m[idx]
}
}
var countsOnesScrubber = [Int](repeating: 0, count: lastBitIndex)
for command in scrubberCommands {
let m = command.map { Bool.init(digit: $0)! }.map { $0 ? 1 : 0 }
countsOnesScrubber.enumerated().forEach { (idx, elem) in
countsOnesScrubber[idx] += m[idx]
}
}
let neededForMajorityOxygen = Int(ceil(Double(oxygenCommands.count) / 2.0))
for command in oxygenCommands {
let idx = command.index(command.startIndex, offsetBy: pos)
let isMostCommon = countsOnesOxygen[pos] >= neededForMajorityOxygen
let digit = Bool(digit: command[idx])
let keepOxygen = digit == isMostCommon
if !keepOxygen, oxygenCommands.count > 1, let coi = oxygenCommands.firstIndex(of: command){
oxygenCommands.remove(at: coi)
}
}
let neededForMajorityScrubber = Int(ceil(Double(scrubberCommands.count) / 2.0))
for command in scrubberCommands {
let idx = command.index(command.startIndex, offsetBy: pos)
let isLeastCommon = countsOnesScrubber[pos] < neededForMajorityScrubber
let digit = Bool(digit: command[idx])
let keepScrubber = digit == isLeastCommon
if !keepScrubber, scrubberCommands.count > 1, let ci = scrubberCommands.firstIndex(of: command) {
scrubberCommands.remove(at: ci)
}
}
}
let finalOxygenNumber = oxygenCommands.first!
let finalScruberNumber = scrubberCommands.first!
print(ToDecimal(num: finalOxygenNumber) * ToDecimal(num: finalScruberNumber))
}
private func ToDecimal(num: String) -> Int {
var pot = -1
var val = 0
for c in num.reversed() {
pot += 1
if c == "0" {
continue
}
val += Int(truncating: NSDecimalNumber(decimal: pow(2, pot)))
}
return val
}
}