-
Notifications
You must be signed in to change notification settings - Fork 0
/
Solution_2021_16.swift
128 lines (119 loc) · 4.17 KB
/
Solution_2021_16.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//
// Solution_2021_16.swift
//
//
// Created by Ivan Chalov on 16.12.21.
//
import Foundation
struct Solution_2021_16: Solution {
var input: Input
func run() throws {
let input = try self.input.get()
.map { Int(String($0), radix: 16)! }
.map { String(String($0, radix: 2).reversed()).padding(toLength: 4, withPad: "0", startingAt: 0).reversed() }
.joined()
.map { Int(String($0))! }
// ------- Part 1 -------
func parse1(_ packet: ArraySlice<Int>, p: inout Int) -> Int {
var sum = 0
let version = packet[p..<(p+3)].fromBinary()
sum += version
p += 3
let typeId = packet[p..<(p+3)].fromBinary()
p += 3
if typeId != 4 {
let lengthTypeId = packet[p]
p += 1
if lengthTypeId == 0 {
let totalLength = packet[p..<(p+15)].fromBinary()
p += 15
let curP = p
while p < curP + totalLength {
sum += parse1(packet, p: &p)
}
} else {
let numberOfSubPackets = packet[p..<(p+11)].fromBinary()
p += 11
(1...numberOfSubPackets).forEach { _ in
sum += parse1(packet, p: &p)
}
}
} else {
while packet[p] != 0 {
p += 5
}
p += 5
}
return sum
}
var p = 0
let part1 = parse1(input[...], p: &p)
print(part1)
// ------- Part 2 -------
func parse2(_ packet: ArraySlice<Int>, p: inout Int) -> Int {
var result = 0
_ = packet[p..<(p+3)].fromBinary()
p += 3
let typeId = packet[p..<(p+3)].fromBinary()
p += 3
if typeId != 4 {
let lengthTypeId = packet[p]
p += 1
var subPacketResults = [Int]()
if lengthTypeId == 0 {
let totalLength = packet[p..<(p+15)].fromBinary()
p += 15
let curP = p
while p < curP + totalLength {
subPacketResults.append(parse2(packet, p: &p))
}
} else {
let numberOfSubPackets = packet[p..<(p+11)].fromBinary()
p += 11
(1...numberOfSubPackets).forEach { _ in
subPacketResults.append(parse2(packet, p: &p))
}
}
switch typeId {
case 0:
result = subPacketResults.reduce(0, +)
case 1:
result = subPacketResults.reduce(1, *)
case 2:
result = subPacketResults.min()!
case 3:
result = subPacketResults.max()!
case 5:
result = subPacketResults[0] > subPacketResults[1] ? 1 : 0
case 6:
result = subPacketResults[0] < subPacketResults[1] ? 1 : 0
case 7:
result = subPacketResults[0] == subPacketResults[1] ? 1 : 0
default:
fatalError("unknown typeId")
}
} else {
var value = [Int]()
while packet[p] != 0 {
value.append(contentsOf: packet[(p+1)..<(p+5)])
p += 5
}
value.append(contentsOf: packet[(p+1)..<(p+5)])
p += 5
result = value.fromBinary()
}
return result
}
p = 0
let part2 = parse2(input[...], p: &p)
print(part2)
// ------- Test -------
assert(part1 == 906, "WA")
assert(part2 == 819324480368, "WA")
}
}
private extension Collection where Element == Int {
func fromBinary() -> Int {
self.reversed().reduce((sum: 0, mult: 1)) { acc, x in (acc.sum + x * acc.mult, acc.mult * 2) }.sum
}
}