// // File.swift // // // Created by Max Nuding on 05.12.21. // import Foundation import Runner import Collections struct Day08: Runnable { let inputPath: String func run() { let input = try! String(contentsOfFile: inputPath) let entries = input .trimmingCharacters(in: .newlines) .components(separatedBy: .newlines) .map { $0.components(separatedBy: " | ") } let lines = entries.reduce(into: [String:String](), { $0[$1.first!] = $1[1] }) runA(lines: lines) print(lines.map { runB(line: $0) }.reduce(0, +)) } func runA(lines: [String : String]) { let outputSignals = lines.values .flatMap { $0.components(separatedBy: .whitespaces) } let uniqueOutputSignals = outputSignals .filter { $0.count == 2 || $0.count == 3 || $0.count == 4 || $0.count == 7 } .count print(uniqueOutputSignals) } func runB(line: Dictionary.Element) -> Int { let uniqueInputSignalDict = line.key .components(separatedBy: .whitespaces) .reduce(into: [Int:String](), { switch $1.count { case 2: $0[1] = $1 case 3: $0[7] = $1 case 4: $0[4] = $1 case 7: $0[8] = $1 default: break } }) let outputSignals = line.value.components(separatedBy: .whitespaces) let len = Double(outputSignals.count - 1) return outputSignals.enumerated() .map { Int(pow(10.0, len - Double($0.offset))) * guessDigit(inputSignals: uniqueInputSignalDict, outputSignal: $0.element)! } .reduce(0, +) } func guessDigit(inputSignals: [Int:String], outputSignal: String) -> Int? { switch outputSignal.count { case 2: return 1 case 3: return 7 case 4: return 4 case 5: if inputSignals[1]!.allSatisfy({ outputSignal.contains($0) }) { return 3 } let isTwo = inputSignals[8]! .filter { !inputSignals[4]!.contains($0) } .allSatisfy { outputSignal.contains($0) } return isTwo ? 2 : 5 case 6: if inputSignals[4]!.allSatisfy({ outputSignal.contains($0) }) { return 9 } let isZero = inputSignals[7]!.allSatisfy { outputSignal.contains($0) } return isZero ? 0 : 6 case 7: return 8 default: print("Invalid output signal: \(outputSignal)") return nil } } }