// // File.swift // // // Created by Max Nuding on 15.12.21. // import Foundation import Runner import Collections 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.ToBinary().joined() let packets = parsePacket(bytes: bytes) let p: Packet = packets.0 print(p.getTotalVersion()) print(p.getValue()) } func parsePacket(bytes: String) -> (Packet, String) { let version = bytes[bytes.startIndex.. ([Packet], String) { 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: String) -> (Int, String) { var index = bytes.index(bytes.startIndex, offsetBy: 6) var ei = index var bits = "" var reminder = "" 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 { self.reversed().enumerated().reduce(0, { p, cur in p + (cur.element == "0" ? 0 : Int(pow(2.0, Double(cur.offset)))) }) } } extension Character { var bits: String { switch self { 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 "A": return "1010" case "B": return "1011" case "C": return "1100" case "D": return "1101" case "E": return "1110" case "F": return "1111" default: fatalError() } } }