Skip to content

Commit 852bfd8

Browse files
committed
Feels like BITS will return before the end, still 4,8 & 9 unfilled so 2 to 3 more days with this is likely
1 parent 9a2d23a commit 852bfd8

File tree

3 files changed

+204
-185
lines changed

3 files changed

+204
-185
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
package com.codingnagger.bits;
2+
3+
import com.codingnagger.days.Day;
4+
5+
import java.math.BigDecimal;
6+
import java.math.BigInteger;
7+
import java.util.ArrayList;
8+
import java.util.Arrays;
9+
import java.util.LinkedList;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.stream.Collectors;
13+
14+
public class Bits {
15+
private static final Map<String, String> HEXA_MAP = Map.ofEntries(
16+
Map.entry("0", "0000"), Map.entry("1", "0001"), Map.entry("2", "0010"),
17+
Map.entry("3", "0011"), Map.entry("4", "0100"), Map.entry("5", "0101"),
18+
Map.entry("6", "0110"), Map.entry("7", "0111"), Map.entry("8", "1000"),
19+
Map.entry("9", "1001"), Map.entry("A", "1010"), Map.entry("B", "1011"),
20+
Map.entry("C", "1100"), Map.entry("D", "1101"), Map.entry("E", "1110"),
21+
Map.entry("F", "1111"));
22+
23+
private static final String L15_BITS = "0";
24+
private static final String L11_BITS = "1";
25+
26+
private static final int T_LITERAL = 4;
27+
28+
private static final String G_LITERAL_LAST_GROUP = "0";
29+
30+
public static Packet parse(String input) {
31+
String binaryInput = convertHexaToBinaryString(input);
32+
return getPackets(binaryInput);
33+
}
34+
35+
private static Packet getPackets(String binaryInput) {
36+
LinkedList<Character> bitsQueue = Arrays.stream(binaryInput.split("")).filter(s -> !s.isBlank()).map(s -> s.charAt(0)).collect(Collectors.toCollection(LinkedList::new));
37+
return readPacket(bitsQueue).getPacket();
38+
}
39+
40+
private static PacketReadResult readPacket(LinkedList<Character> bitsQueue) {
41+
int packetVersion = Integer.parseInt(readBits(bitsQueue, 3), 2);
42+
int packetTypeId = Integer.parseInt(readBits(bitsQueue, 3), 2);
43+
int readBits = 6;
44+
45+
if (packetTypeId == T_LITERAL) {
46+
StringBuilder binaryContentsBuilder = new StringBuilder();
47+
48+
while(!G_LITERAL_LAST_GROUP.equals(readBits(bitsQueue, 1))) {
49+
binaryContentsBuilder.append(readBits(bitsQueue, 4));
50+
readBits += 5;
51+
}
52+
53+
binaryContentsBuilder.append(readBits(bitsQueue, 4));
54+
readBits += 5;
55+
56+
return new PacketReadResult(new LiteralPacket(packetVersion, packetTypeId, binaryContentsBuilder.toString()), readBits);
57+
} else {
58+
String lengthTypeId = readBits(bitsQueue, 1);
59+
List<Packet> children = new ArrayList<>();
60+
61+
if (L15_BITS.equals(lengthTypeId)) {
62+
int bitsToRead = Integer.parseInt(readBits(bitsQueue, 15), 2);
63+
64+
LinkedList<Character> childrenBitsToRead = new LinkedList<>();
65+
66+
for (int i = 0; i < bitsToRead; i++) {
67+
childrenBitsToRead.add(bitsQueue.poll());
68+
}
69+
70+
while (!childrenBitsToRead.isEmpty()) {
71+
PacketReadResult res = readPacket(childrenBitsToRead);
72+
73+
bitsToRead -= res.getReadBits();
74+
readBits += res.getReadBits();
75+
children.add(res.getPacket());
76+
}
77+
78+
System.out.printf("Bits left to read: %d%n", bitsToRead);
79+
} else if (L11_BITS.equals(lengthTypeId)) {
80+
int childrenToRead = Integer.parseInt(readBits(bitsQueue, 11), 2);
81+
82+
while (childrenToRead > 0) {
83+
PacketReadResult res = readPacket(bitsQueue);
84+
85+
readBits += res.getReadBits();
86+
children.add(res.getPacket());
87+
childrenToRead--;
88+
}
89+
}
90+
91+
return new PacketReadResult(new OperationPacket(packetVersion, packetTypeId, children), readBits);
92+
}
93+
}
94+
95+
private static String readBits(LinkedList<Character> bitsQueue, int count) {
96+
StringBuilder sb = new StringBuilder(count);
97+
98+
for (int i = 0; i < count; i++) {
99+
sb.append(bitsQueue.poll());
100+
}
101+
102+
return sb.toString();
103+
}
104+
105+
public static String convertHexaToBinaryString(String hexa) {
106+
return Arrays.stream(hexa.split("")).map(HEXA_MAP::get).collect(Collectors.joining(""));
107+
}
108+
109+
static class PacketReadResult {
110+
private final Packet packet;
111+
private final int readBits;
112+
113+
public PacketReadResult(Packet packet, int readBits) {
114+
this.packet = packet;
115+
this.readBits = readBits;
116+
}
117+
118+
public Packet getPacket() {
119+
return packet;
120+
}
121+
122+
public int getReadBits() {
123+
return readBits;
124+
}
125+
}
126+
127+
public static abstract class Packet {
128+
private final int packetVersion;
129+
private final int packetTypeId;
130+
131+
public Packet(int packetVersion, int packetTypeId) {
132+
this.packetVersion = packetVersion;
133+
this.packetTypeId = packetTypeId;
134+
}
135+
136+
public int getPacketVersion() {
137+
return packetVersion;
138+
}
139+
140+
public int getPacketTypeId() {
141+
return packetTypeId;
142+
}
143+
144+
public int getVersionSum() {
145+
return packetVersion;
146+
}
147+
148+
public abstract BigDecimal computeValue();
149+
}
150+
151+
static class LiteralPacket extends Packet {
152+
private final String binaryContents;
153+
154+
public LiteralPacket(int packetVersion, int packetTypeId, String binaryContents) {
155+
super(packetVersion, packetTypeId);
156+
this.binaryContents = binaryContents;
157+
}
158+
159+
public String getBinaryContents() {
160+
return binaryContents;
161+
}
162+
163+
public BigDecimal computeValue() {
164+
return new BigDecimal(new BigInteger(binaryContents, 2).longValue());
165+
}
166+
}
167+
168+
static class OperationPacket extends Packet {
169+
private final List<Packet> subPackets;
170+
171+
public OperationPacket(int packetVersion, int packetTypeId, List<Packet> subPackets) {
172+
super(packetVersion, packetTypeId);
173+
this.subPackets = subPackets;
174+
}
175+
176+
@Override
177+
public int getVersionSum() {
178+
return getPacketVersion() + subPackets.stream().mapToInt(Packet::getVersionSum).sum();
179+
}
180+
181+
public BigDecimal computeValue() {
182+
switch (getPacketTypeId()) {
183+
case 0: return subPackets.stream().map(Packet::computeValue).reduce(BigDecimal.ZERO, BigDecimal::add);
184+
case 1: return subPackets.stream().map(Packet::computeValue).reduce(BigDecimal.ONE, BigDecimal::multiply);
185+
case 2: return subPackets.stream().map(Packet::computeValue).reduce(BigDecimal.valueOf(Long.MAX_VALUE), BigDecimal::min);
186+
case 3: return subPackets.stream().map(Packet::computeValue).reduce(BigDecimal.valueOf(Long.MIN_VALUE), BigDecimal::max);
187+
188+
case 5: return subPackets.get(0).computeValue().compareTo(subPackets.get(1).computeValue()) > 0 ? BigDecimal.ONE : BigDecimal.ZERO;
189+
case 6: return subPackets.get(0).computeValue().compareTo(subPackets.get(1).computeValue()) < 0 ? BigDecimal.ONE : BigDecimal.ZERO;
190+
case 7: return subPackets.get(0).computeValue().equals(subPackets.get(1).computeValue() ) ? BigDecimal.ONE : BigDecimal.ZERO;
191+
}
192+
193+
return null;
194+
}
195+
}
196+
}

0 commit comments

Comments
 (0)