my advent of code solutions
at main 88 lines 3.2 kB view raw
1namespace Solutions._2021; 2 3/// <summary> 4/// Day 16: <a href="https://adventofcode.com/2021/day/16"/> 5/// </summary> 6public sealed class Day16PacketDecoder() : Day(2021, 16, "Packet Decoder") 7{ 8 private Packet? _packet; 9 10 public override void ProcessInput() 11 { 12 var bits = Input.First() 13 .Select(c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0')) 14 .Join(); 15 (_packet, _) = Packet.FromBinaryString(bits); 16 } 17 18 private record Packet(int Version, int TypeId, long Value, List<Packet> Packets) 19 { 20 public static (Packet packet, int offset) FromBinaryString(string input) 21 { 22 var index = 0; 23 var subPackets = new List<Packet>(); 24 var version = Convert.ToInt32(input[..(index += 3)], 2); 25 var typeId = Convert.ToInt32(input[index..(index += 3)], 2); 26 27 if (typeId == 4) 28 { 29 // value packet, gather value bits and return right away 30 var literalBits = new StringBuilder(); 31 foreach (var chunk in input.Skip(index).Chunk(5)) 32 { 33 literalBits.Append(chunk[1..5]); 34 index += 5; 35 if (chunk[0] == '0') break; 36 } 37 38 return (new(version, typeId, Convert.ToInt64(literalBits.ToString(), 2), []), index); 39 } 40 41 switch (input[index++]) 42 { 43 case '0': 44 var subPacketLength = Convert.ToInt32(input[index..(index += 15)], 2); 45 while (subPacketLength > 0) 46 { 47 var (packet, offset) = FromBinaryString(input[index..(index + subPacketLength)]); 48 subPackets.Add(packet); 49 subPacketLength -= offset; 50 index += offset; 51 } 52 53 break; 54 case '1': 55 foreach (var _ in Enumerable.Range(0, Convert.ToInt32(input[index..(index += 11)], 2))) 56 { 57 var (packet, offset) = FromBinaryString(input[index..]); 58 subPackets.Add(packet); 59 index += offset; 60 } 61 62 break; 63 } 64 65 return (new(version, typeId, 0, subPackets), index); 66 } 67 68 public long VersionTotal => Version + Packets.Sum(p => p.VersionTotal); 69 70 public long Eval => 71 TypeId switch 72 { 73 0 => Packets.Sum(p => p.Eval), 74 1 => Packets.Aggregate(1L, (p, i) => p * i.Eval), 75 2 => Packets.Min(p => p.Eval), 76 3 => Packets.Max(p => p.Eval), 77 4 => Value, 78 5 => Packets[0].Eval > Packets[1].Eval ? 1 : 0, 79 6 => Packets[0].Eval < Packets[1].Eval ? 1 : 0, 80 7 => Packets[0].Eval == Packets[1].Eval ? 1 : 0, 81 _ => throw new ArgumentException("invalid packet type", nameof(TypeId)), 82 }; 83 } 84 85 public override object Part1() => _packet!.VersionTotal; 86 87 public override object Part2() => _packet!.Eval; 88}