-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpuzzle1.ts
107 lines (86 loc) · 2.72 KB
/
puzzle1.ts
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
import { readInput } from '../utils';
class TransmissionDecoder {
private operatorMetaBits = 7;
private literalMetaBits = 6;
private packetVersionSum = 0;
decode(message: string) {
const binary = this.toBinary(message);
this.decodePacket(binary);
return this.packetVersionSum;
}
private toBinary(message: string) {
return message
.split('')
.map((hex) => parseInt(hex, 16).toString(2).padStart(4, '0'))
.join('');
}
private decodePacket(packet: string): { decodedBits: number } {
const version = parseInt(packet.slice(0, 3), 2);
const typeId = parseInt(packet.slice(3, 6), 2);
this.packetVersionSum += version;
return this.isLiteral(typeId)
? this.decodeLiteral(packet)
: this.decodeOperator(packet);
}
private decodeLiteral(packet: string) {
const packetData = packet.slice(this.literalMetaBits);
let accumulatedNumber = '';
let i = 0;
while (true) {
accumulatedNumber += packetData.slice(i + 1, i + 5);
if (packetData[i] === '0') {
i += 5;
break;
}
i += 5;
}
const literal = parseInt(accumulatedNumber, 2);
const decodedBits = this.literalMetaBits + i;
return { literal, decodedBits };
}
private decodeOperator(packet: string) {
// 7th bit
return packet[6] === '0'
? this.decodeOperatorType0(packet)
: this.decodeOperatorType1(packet);
}
private decodeOperatorType0(packet: string) {
const lengthTypeEndBit = this.operatorMetaBits + 15;
const lengthInBits = parseInt(
packet.slice(this.operatorMetaBits, lengthTypeEndBit),
2
);
let startPosition = lengthTypeEndBit;
while (startPosition !== lengthTypeEndBit + lengthInBits) {
const decoded = this.decodePacket(
packet.slice(startPosition, lengthTypeEndBit + lengthInBits)
);
startPosition += decoded.decodedBits;
}
return { decodedBits: startPosition };
}
private decodeOperatorType1(packet: string) {
let lengthTypeEndBit = this.operatorMetaBits + 11;
const numberOfSubpackets = parseInt(
packet.slice(this.operatorMetaBits, lengthTypeEndBit),
2
);
let numberOfReadPackets = 0;
let startingBit = lengthTypeEndBit;
while (numberOfReadPackets < numberOfSubpackets) {
const decoded = this.decodePacket(packet.slice(startingBit));
numberOfReadPackets++;
startingBit += decoded.decodedBits;
}
return { decodedBits: startingBit };
}
private isLiteral(typeId: number) {
return typeId === 4;
}
}
function solve(fileName: string) {
const decoder = new TransmissionDecoder();
const [line] = readInput(fileName);
return decoder.decode(line);
}
console.log('Solution:', solve('./input'));