This commit is contained in:
Max Nuding 2021-12-16 18:55:25 +01:00
parent 7326d17948
commit 632868f7f3
Signed by: phlaym
GPG Key ID: A06651BAB6777237

View File

@ -76,18 +76,18 @@ class Day16: Runnable {
let input = try! String(contentsOfFile: inputPath) let input = try! String(contentsOfFile: inputPath)
let parts = input let parts = input
.trimmingCharacters(in: .newlines) .trimmingCharacters(in: .newlines)
let bytes = parts.ToBinary().joined() let bytes = parts.bits().joined()
let packets = parsePacket(bytes: bytes) let packets = parsePacket(bytes: bytes)
let p: Packet = packets.0 let p: Packet = packets.0
print(p.getTotalVersion()) print(p.getTotalVersion())
print(p.getValue()) print(p.getValue())
} }
func parsePacket(bytes: String) -> (Packet, String) { func parsePacket<S>(bytes: S) -> (Packet, S.SubSequence) where S:StringProtocol {
let version = bytes[bytes.startIndex..<bytes.index(bytes.startIndex, offsetBy: 3)].description.binaryToDecimal() let version = bytes[bytes.startIndex..<bytes.index(bytes.startIndex, offsetBy: 3)].binaryToDecimal()
let typeId = bytes[bytes.index(bytes.startIndex, offsetBy: 3)..<bytes.index(bytes.startIndex, offsetBy: 6)].description.binaryToDecimal() let typeId = bytes[bytes.index(bytes.startIndex, offsetBy: 3)..<bytes.index(bytes.startIndex, offsetBy: 6)].binaryToDecimal()
var value: Packet var value: Packet
var reminder: String var reminder: S.SubSequence
switch typeId { switch typeId {
case 4: case 4:
let (v, r) = parseLiteralPacketValue(bytes: bytes) let (v, r) = parseLiteralPacketValue(bytes: bytes)
@ -101,17 +101,17 @@ class Day16: Runnable {
return (value, reminder) return (value, reminder)
} }
func parseOperatorPacker(bytes: String) -> ([Packet], String) { func parseOperatorPacker<S>(bytes: S) -> ([Packet], S.SubSequence) where S:StringProtocol {
let startNextBitsIndex = bytes.index(bytes.startIndex, offsetBy: 7) let startNextBitsIndex = bytes.index(bytes.startIndex, offsetBy: 7)
let lengthTypeId = bytes[bytes.index(bytes.startIndex, offsetBy: 6)..<startNextBitsIndex].description let lengthTypeId = bytes[bytes.index(bytes.startIndex, offsetBy: 6)..<startNextBitsIndex].description
let isTotalLength = lengthTypeId == "0" let isTotalLength = lengthTypeId == "0"
let nextBitsLength = isTotalLength ? 15 : 11 let nextBitsLength = isTotalLength ? 15 : 11
let endNextBitsIndex = bytes.index(startNextBitsIndex, offsetBy: nextBitsLength) let endNextBitsIndex = bytes.index(startNextBitsIndex, offsetBy: nextBitsLength)
let nextBits = bytes[startNextBitsIndex..<endNextBitsIndex].description let nextBits = bytes[startNextBitsIndex..<endNextBitsIndex]
var number = nextBits.binaryToDecimal() var number = nextBits.binaryToDecimal()
var reminder = bytes[endNextBitsIndex...].description var reminder = bytes[endNextBitsIndex...]
var subPackets = [Packet]() var subPackets = [Packet]()
while number > 0 { while number > 0 {
@ -123,17 +123,17 @@ class Day16: Runnable {
return (subPackets, reminder) return (subPackets, reminder)
} }
func parseLiteralPacketValue(bytes: String) -> (Int, String) { func parseLiteralPacketValue<S>(bytes: S) -> (Int, S.SubSequence) where S:StringProtocol {
var index = bytes.index(bytes.startIndex, offsetBy: 6) var index = bytes.index(bytes.startIndex, offsetBy: 6)
var ei = index var ei = index
var bits = "" var bits: Substring = ""
var reminder = "" var reminder: S.SubSequence = ""
while true { while true {
let si = bytes.index(index, offsetBy: 1) let si = bytes.index(index, offsetBy: 1)
ei = bytes.index(si, offsetBy: 4) ei = bytes.index(si, offsetBy: 4)
bits += bytes[si..<ei].description bits += bytes[si..<ei]
if bytes[index] == "0" { if bytes[index] == "0" {
reminder = bytes[ei...].description reminder = bytes[ei...]
break break
} }
index = bytes.index(ei, offsetBy: 0) index = bytes.index(ei, offsetBy: 0)
@ -142,52 +142,48 @@ class Day16: Runnable {
} }
} }
extension String { extension StringProtocol {
func ToBinary() -> [String] { func bits() -> [String] {
self.map { $0.bits } self.map { $0.bits }
} }
func binaryToDecimal() -> Int { func binaryToDecimal() -> Int { Int(self, radix: 2)! }
self.reversed().enumerated().reduce(0, { p, cur in
p + (cur.element == "0" ? 0 : Int(pow(2.0, Double(cur.offset))))
})
}
} }
extension Character { extension Character {
var bits: String { var bits: String {
switch self { switch self.hexDigitValue! {
case "0": case 0:
return "0000" return "0000"
case "1": case 1:
return "0001" return "0001"
case "2": case 2:
return "0010" return "0010"
case "3": case 3:
return "0011" return "0011"
case "4": case 4:
return "0100" return "0100"
case "5": case 5:
return "0101" return "0101"
case "6": case 6:
return "0110" return "0110"
case "7": case 7:
return "0111" return "0111"
case "8": case 8:
return "1000" return "1000"
case "9": case 9:
return "1001" return "1001"
case "A": case 10:
return "1010" return "1010"
case "B": case 11:
return "1011" return "1011"
case "C": case 12:
return "1100" return "1100"
case "D": case 13:
return "1101" return "1101"
case "E": case 14:
return "1110" return "1110"
case "F": case 15:
return "1111" return "1111"
default: default:
fatalError() fatalError()