// // File.swift // // // Created by Max Nuding on 15.12.21. // import Foundation import Runner enum OperatorType: Int { case sum = 0 case product = 1 case minimum = 2 case maximum = 3 case value = 4 case greaterThan = 5 case lessThan = 6 case equal = 7 } protocol Packet { var version: Int { get } func getTotalVersion() -> Int func getValue() -> Int } struct ValuePacket: Packet { let version: Int let value: Int func getTotalVersion() -> Int { version } func getValue() -> Int { value } } struct OperatorPacket: Packet { let type: OperatorType let version: Int let subPackets: [Packet] func getTotalVersion() -> Int { version + subPackets.map { $0.getTotalVersion() }.reduce(0, +) } func getValue() -> Int { let spValues = subPackets.map { $0.getValue() } switch type { case .sum: return spValues.reduce(0, +) case .product: return spValues.reduce(1, *) case .minimum: return spValues.min()! case .maximum: return spValues.max()! case .greaterThan: return spValues.first! > spValues.last! ? 1 : 0 case .lessThan: return spValues.first! < spValues.last! ? 1 : 0 case .equal: return spValues.first! == spValues.last! ? 1 : 0 case .value: fatalError() } } } class Day16: 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) let bytes = parts.bits().joined() let packets = parsePacket(bytes: bytes) let p: Packet = packets.0 print(p.getTotalVersion()) print(p.getValue()) } func parsePacket(bytes: S) -> (Packet, S.SubSequence) where S:StringProtocol { let version = bytes[bytes.startIndex..(bytes: S) -> ([Packet], S.SubSequence) where S:StringProtocol { let startNextBitsIndex = bytes.index(bytes.startIndex, offsetBy: 7) let lengthTypeId = bytes[bytes.index(bytes.startIndex, offsetBy: 6).. 0 { let (p, rem) = parsePacket(bytes: reminder) number -= isTotalLength ? (reminder.count - rem.count) : 1 subPackets.append(p) reminder = rem } return (subPackets, reminder) } func parseLiteralPacketValue(bytes: S) -> (Int, S.SubSequence) where S:StringProtocol { var index = bytes.index(bytes.startIndex, offsetBy: 6) var ei = index var bits: Substring = "" var reminder: S.SubSequence = "" while true { let si = bytes.index(index, offsetBy: 1) ei = bytes.index(si, offsetBy: 4) bits += bytes[si.. [String] { self.map { $0.bits } } func binaryToDecimal() -> Int { Int(self, radix: 2)! } } extension Character { var bits: String { switch self.hexDigitValue! { case 0: return "0000" case 1: return "0001" case 2: return "0010" case 3: return "0011" case 4: return "0100" case 5: return "0101" case 6: return "0110" case 7: return "0111" case 8: return "1000" case 9: return "1001" case 10: return "1010" case 11: return "1011" case 12: return "1100" case 13: return "1101" case 14: return "1110" case 15: return "1111" default: fatalError() } } }