Skip to content

Commit af4757d

Browse files
committed
day16 comments
1 parent c0f527a commit af4757d

File tree

1 file changed

+46
-31
lines changed

1 file changed

+46
-31
lines changed

2021/Day16/Solution.cs

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,92 +8,107 @@ namespace AdventOfCode.Y2021.Day16;
88
class Solution : Solver {
99

1010
public object PartOne(string input) =>
11-
GetTotalVersion(GetPacket(GetInput(input)));
11+
GetTotalVersion(GetPacket(GetReader(input)));
1212

1313
public object PartTwo(string input) =>
14-
Evaluate(GetPacket(GetInput(input)));
14+
Evaluate(GetPacket(GetReader(input)));
1515

16+
// recursively sum the versions of a packet and its content for part 1:
17+
int GetTotalVersion(Packet packet) =>
18+
packet.version + packet.packets.Select(GetTotalVersion).Sum();
19+
20+
// recursively evaluate the packet and its contents based on the type tag for part 2:
1621
long Evaluate(Packet packet) {
1722
var parts = packet.packets.Select(Evaluate).ToArray();
1823
return packet.type switch {
1924
0 => parts.Sum(),
2025
1 => parts.Aggregate(1L, (acc, x) => acc * x),
2126
2 => parts.Min(),
2227
3 => parts.Max(),
23-
4 => packet.payload,
28+
4 => packet.payload, // <--- literal packet is handled uniformly
2429
5 => parts[0] > parts[1] ? 1 : 0,
2530
6 => parts[0] < parts[1] ? 1 : 0,
2631
7 => parts[0] == parts[1] ? 1 : 0,
2732
_ => throw new Exception()
2833
};
2934
}
3035

31-
int GetTotalVersion(Packet packet) =>
32-
packet.version + packet.packets.Select(GetTotalVersion).Sum();
36+
// convert hex string to bit sequence reader
37+
BitSequenceReader GetReader(string input) => new BitSequenceReader(
38+
from hexChar in input
39+
40+
// first get the 4 bits out of a hex char:
41+
let value = Convert.ToInt32(hexChar.ToString(), 16)
42+
let nibble = Convert.ToString(value, 2).PadLeft(4, '0')
3343

34-
Input GetInput(string input) => new Input(
35-
(from ch in input
36-
let bits = Convert.ToString(Convert.ToInt32(ch.ToString(), 16), 2).PadLeft(4, '0')
37-
from bit in bits
38-
select bit - '0').ToList()
44+
// then convert them to numbers:
45+
from bitChar in nibble
46+
select (byte)(bitChar - '0')
3947
);
4048

41-
Packet GetPacket(Input input) {
42-
var version = input.ReadInt(3);
43-
var type = input.ReadInt(3);
49+
// make sense of the bit sequence:
50+
Packet GetPacket(BitSequenceReader reader) {
51+
var version = reader.ReadInt(3);
52+
var type = reader.ReadInt(3);
4453
var packets = new List<Packet>();
4554
var payload = 0L;
4655

4756
if (type == 0x4) {
57+
// literal, payload is encoded in the following bits in 5 bit long chunks:
4858
while (true) {
49-
var isLast = input.ReadInt(1) == 0;
50-
payload = payload * 16 + input.ReadInt(4);
59+
var isLast = reader.ReadInt(1) == 0;
60+
payload = payload * 16 + reader.ReadInt(4);
5161
if (isLast) {
5262
break;
5363
}
5464
}
55-
} else if (input.ReadInt(1) == 0) {
56-
var length = input.ReadInt(15);
57-
var subPackages = input.ReadInput(length);
65+
} else if (reader.ReadInt(1) == 0) {
66+
// operator, the next 'length' long bit sequence encodes the sub packages:
67+
var length = reader.ReadInt(15);
68+
var subPackages = reader.GetBitSequenceReader(length);
5869
while (subPackages.Any()) {
5970
packets.Add(GetPacket(subPackages));
6071
}
6172
} else {
62-
var packetCount = input.ReadInt(11);
63-
packets.AddRange(from _ in Enumerable.Range(0, packetCount) select GetPacket(input));
73+
// operator with 'packetCount' sub packages:
74+
var packetCount = reader.ReadInt(11);
75+
packets.AddRange(from _ in Enumerable.Range(0, packetCount) select GetPacket(reader));
6476
}
6577

6678
return new Packet(version, type, payload, packets.ToArray());
6779
}
6880
}
6981

70-
class Input {
71-
private List<int> bits;
82+
// Rader class with convenience methods to retrieve n-bit integers and subreaders as needed
83+
class BitSequenceReader {
84+
private List<byte> bits;
7285
private int ptr;
7386

74-
public Input(List<int> numbers) {
75-
this.bits = numbers;
87+
public BitSequenceReader(IEnumerable<byte> bits) {
88+
// copying the input, and representing each bit with a byte is not very attracitve,
89+
// but it's aoc time....
90+
this.bits = bits.ToList();
7691
}
7792

7893
public bool Any() {
7994
return ptr < bits.Count();
8095
}
8196

82-
public Input ReadInput(int n) {
83-
var sub = bits.GetRange(ptr, n).ToList();
84-
var res = new Input(sub);
85-
ptr += n;
97+
public BitSequenceReader GetBitSequenceReader(int bitCount) {
98+
var res = new BitSequenceReader(bits.GetRange(ptr, bitCount));
99+
ptr += bitCount;
86100
return res;
87101
}
88102

89-
public int ReadInt(int n) {
103+
public int ReadInt(int bitCount) {
90104
var res = 0;
91-
foreach (var bit in bits.GetRange(ptr, n)) {
105+
foreach (var bit in bits.GetRange(ptr, bitCount)) {
92106
res = res * 2 + bit;
93107
}
94-
ptr += n;
108+
ptr += bitCount;
95109
return res;
96110
}
97111
}
98112

113+
// Each packet has all fields, type tag tells how to interpret the contents
99114
record Packet(int version, int type, long payload, Packet[] packets);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy