#pragma warning disable CS8600 //Because fuck warnings, that's why class Program { static void Main(string[] args) { string input; Dictionary<char, string> hexMap = new Dictionary<char, string>(); hexMap.Add('0', "0000"); hexMap.Add('1', "0001"); hexMap.Add('2', "0010"); hexMap.Add('3', "0011"); hexMap.Add('4', "0100"); hexMap.Add('5', "0101"); hexMap.Add('6', "0110"); hexMap.Add('7', "0111"); hexMap.Add('8', "1000"); hexMap.Add('9', "1001"); hexMap.Add('A', "1010"); hexMap.Add('B', "1011"); hexMap.Add('C', "1100"); hexMap.Add('D', "1101"); hexMap.Add('E', "1110"); hexMap.Add('F', "1111"); using (StreamReader sr = new StreamReader(@"../../../../Input.in")) { input = sr.ReadLine(); } string bits = ""; foreach (char c in input) { bits += hexMap[c]; } Packet recv = new Packet(); recv.Read(bits, false, 0); long sumVer = VersionSum(recv); ulong ans = Eval(recv); Console.WriteLine("The sum of version numbers is " + sumVer.ToString()); Console.WriteLine("The evaluated expression sent gives " + ans.ToString() + " as a result"); } static long VersionSum(Packet p) { long subSum = 0; if (p.subPackets.Count == 0) { return p.version; } else { foreach (Packet s in p.subPackets) { subSum += VersionSum(s); } subSum += p.version; } return subSum; } public static ulong Eval(Packet p) { if (p.typeID == 4) return p.literalValue; else { switch (p.typeID) { case 0: ulong sumValue = 0; foreach (Packet s in p.subPackets) sumValue += Eval(s); return sumValue; case 1: ulong prodValue = 1; foreach (Packet s in p.subPackets) prodValue *= Eval(s); return prodValue; case 2: ulong minValue = ulong.MaxValue; foreach (Packet s in p.subPackets) { ulong curr = Eval(s); minValue = curr < minValue ? curr : minValue; } return minValue; case 3: // this is a maximum of sub breaks ulong maxValue = ulong.MinValue; foreach (Packet s in p.subPackets) { ulong curr = Eval(s); maxValue = curr > maxValue ? curr : maxValue; } return maxValue; case 5: // this is a greater than of sub breaks ulong sub1 = Eval(p.subPackets[0]); ulong sub2 = Eval(p.subPackets[1]); return (ulong)(sub1 > sub2 ? 1 : 0); case 6: // this is a less than of sub breaks sub1 = Eval(p.subPackets[0]); sub2 = Eval(p.subPackets[1]); return (ulong)(sub1 < sub2 ? 1 : 0); case 7: // this is a equal than of sub breaks sub1 = Eval(p.subPackets[0]); sub2 = Eval(p.subPackets[1]); return (ulong)(sub1 == sub2 ? 1 : 0); } } return 0; } } public class Packet { public int version; public int typeID; public List<Packet> subPackets; public int lengthTypeID; public ulong literalValue; public Packet() { subPackets = new List<Packet>(); } public int Read(string packetSTR, bool isSub, int packetStart) { int totBitsRead = 0; string verStr = packetSTR.Substring(packetStart, 3); string typeStr = packetSTR.Substring(packetStart + 3, 3); totBitsRead += 6; version = Convert.ToInt32(verStr, 2); typeID = Convert.ToInt32(typeStr, 2); if (typeID != 4) { lengthTypeID = Convert.ToInt32(packetSTR.Substring(packetStart + totBitsRead, 1), 2); totBitsRead += 1; if (lengthTypeID == 0) //read 15 bits to get total length of sub packets in bits { int subPacketsTotLength = Convert.ToInt32(packetSTR.Substring(packetStart + totBitsRead, 15), 2); totBitsRead += 15; int subPacketBits = 0; int offset = 0; //Console.WriteLine("Length Type:{0}, Sub Packet Bit Length:{1}",lengthTypeID, subPacketsTotLength); while (subPacketBits < subPacketsTotLength) { Packet sub = new Packet(); offset = sub.Read(packetSTR, true, packetStart + totBitsRead); subPacketBits += offset; totBitsRead += offset; subPackets.Add(sub); } } else // read 11 bits which is number of packets to read { int numPackets = Convert.ToInt32(packetSTR.Substring(packetStart + totBitsRead, 11), 2); totBitsRead += 11; int offset = 0; //Console.WriteLine("Length Type:{0}, numPackets:{1}", lengthTypeID, numPackets); for (int i = 0; i < numPackets; i++) { Packet sub = new Packet(); offset = sub.Read(packetSTR, true, packetStart + totBitsRead); totBitsRead += offset; subPackets.Add(sub); } } } else { int bitsRead; //Console.WriteLine("Reading Literal"); (bitsRead, literalValue) = ParseType(packetSTR.Substring(packetStart + 6), isSub); //Console.WriteLine("Read Literal bitsRead:{0}, litValue:{0}", bitsRead, literalValue); totBitsRead += bitsRead; } return totBitsRead; //Console.WriteLine("Finished reading packet"); } public (int, ulong) ParseType(string literalPayload, bool isSub) { string payload = ""; bool foundZero = false; int numChunks = 0; while (!foundZero) { string chunk = literalPayload.Substring(numChunks * 5, 5); if (chunk[0] == '0') { foundZero = true; } payload += chunk.Substring(1, 4); numChunks++; } ulong litValue = Convert.ToUInt64(payload, 2); int bitsRead = numChunks * 5; return (bitsRead, litValue); } }