From 542df5bd8c64f452ab7c6ab9c3e200b987f25a9a Mon Sep 17 00:00:00 2001 From: Parnic Date: Thu, 16 Dec 2021 09:23:08 -0600 Subject: [PATCH] Day 16, extreme parsing edition --- advent-of-code-2021.csproj | 3 + inputs/16.txt | 1 + src/16.cs | 165 +++++++++++++++++++++++++++++++++++++ src/main.cs | 3 +- 4 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 inputs/16.txt create mode 100644 src/16.cs diff --git a/advent-of-code-2021.csproj b/advent-of-code-2021.csproj index 160437f..efdfd38 100644 --- a/advent-of-code-2021.csproj +++ b/advent-of-code-2021.csproj @@ -63,6 +63,9 @@ PreserveNewest + + PreserveNewest + diff --git a/inputs/16.txt b/inputs/16.txt new file mode 100644 index 0000000..bef9be8 --- /dev/null +++ b/inputs/16.txt @@ -0,0 +1 @@ +A20D5080210CE4BB9BAFB001BD14A4574C014C004AE46A9B2E27297EECF0C013F00564776D7E3A825CAB8CD47B6C537DB99CD746674C1000D29BBC5AC80442966FB004C401F8771B61D8803D0B22E4682010EE7E59ACE5BC086003E3270AE4024E15C8010073B2FAD98E004333F9957BCB602E7024C01197AD452C01295CE2DC9934928B005DD258A6637F534CB3D89A944230043801A596B234B7E58509E88798029600BCF5B3BA114F5B3BA10C9E77BAF20FA4016FCDD13340118B929DD4FD54E60327C00BEB7002080AA850031400D002369400B10034400F30021400F20157D804AD400FE00034E000A6D001EB2004E5C00B9AE3AC3C300470029091ACADBFA048D656DFD126792187008635CD736B3231A51BA5EBDF42D4D299804F26B33C872E213C840022EC9C21FFB34EDE7C559C8964B43F8AD77570200FC66697AFEB6C757AC0179AB641E6AD9022006065CEA714A4D24C0179F8E795D3078026200FC118EB1B40010A8D11EA27100990200C45A83F12C401A8611D60A0803B1723542889537EFB24D6E0844004248B1980292D608D00423F49F9908049798B4452C0131006230C14868200FC668B50650043196A7F95569CF6B663341535DCFE919C464400A96DCE1C6B96D5EEFE60096006A400087C1E8610A4401887D1863AC99F9802DC00D34B5BCD72D6F36CB6E7D95EBC600013A88010A8271B6281803B12E124633006A2AC3A8AC600BCD07C9851008712DEAE83A802929DC51EE5EF5AE61BCD0648028596129C3B98129E5A9A329ADD62CCE0164DDF2F9343135CCE2137094A620E53FACF37299F0007392A0B2A7F0BA5F61B3349F3DFAEDE8C01797BD3F8BC48740140004322246A8A2200CC678651AA46F09AEB80191940029A9A9546E79764F7C9D608EA0174B63F815922999A84CE7F95C954D7FD9E0890047D2DC13B0042488259F4C0159922B0046565833828A00ACCD63D189D4983E800AFC955F211C700 \ No newline at end of file diff --git a/src/16.cs b/src/16.cs new file mode 100644 index 0000000..1ed4718 --- /dev/null +++ b/src/16.cs @@ -0,0 +1,165 @@ +using System.Text; + +namespace aoc2021; + +internal class Day16 : Day +{ + internal override void Go() + { + var lines = Util.ReadAllLines("inputs/16.txt"); + var input = lines.ElementAt(0); + var binStr = string.Empty; + foreach (var ch in input) + { + binStr += Convert.ToString(Convert.ToInt64(ch.ToString(), 16), 2).PadLeft(4, '0'); + } + int idx = 0; + using var t = new Timer("Decoding packet"); + (var versionTotal, var result) = DecodePacket(binStr, ref idx); + t.Stop(); + Part1(versionTotal); + Part2(result); + } + + private static void Part1(long versionTotal) + { + Logger.Log($"part1: version total: {versionTotal}"); + } + + private static void Part2(long result) + { + Logger.Log($"part2: operator result: {result}"); + } + + private static (long versionTotal, long result) DecodePacket(string binary, ref int idx) + { + long versionTotal = 0; + + (var version, var typeID) = ParsePacketHeader(binary, ref idx); + versionTotal += version; + long result; + switch (typeID) + { + case 4: + result = ParseLiteralPacket(binary, ref idx); + break; + + default: + (version, result) = ParseOperatorPacket(binary, typeID, ref idx); + versionTotal += version; + break; + } + + return (versionTotal, result); + } + + private static (long, long) ParsePacketHeader(string binary, ref int idx) + { + var version = Convert.ToInt64(binary[idx..(idx + 3)], 2); + idx += 3; + var typeID = Convert.ToInt64(binary[idx..(idx + 3)], 2); + idx += 3; + return (version, typeID); + } + + private static long ParseLiteralPacket(string binary, ref int idx) + { + StringBuilder numStr = new(); + bool done = false; + while (!done) + { + if (binary[idx] == '0') + { + done = true; + } + + numStr.Append(binary[(idx + 1)..(idx + 5)]); + idx += 5; + } + + return Convert.ToInt64(numStr.ToString(), 2); + } + + private static (long versionTotal, long result) ParseOperatorPacket(string binary, long inType, ref int idx) + { + var lengthType = Convert.ToInt64(binary[idx..(idx + 1)], 2); + idx++; + + long totalLength = 0; + long numSubPackets = 0; + switch (lengthType) + { + case 0: + totalLength = Convert.ToInt64(binary[idx..(idx + 15)], 2); + idx += 15; + break; + + case 1: + numSubPackets = Convert.ToInt64(binary[idx..(idx + 11)], 2); + idx += 11; + break; + } + + long versionTotal = 0; + + bool done = false; + int startIdx = idx; + long lengthProcessed = 0; + long subPacketsProcessed = 0; + List operands = new(); + while (!done) + { + (var version, var operand) = DecodePacket(binary, ref idx); + operands.Add(operand); + subPacketsProcessed++; + lengthProcessed = idx - startIdx; + versionTotal += version; + + done = done || (numSubPackets != 0 && subPacketsProcessed == numSubPackets); + done = done || (totalLength != 0 && lengthProcessed == totalLength); + } + + long result = 0; + switch (inType) + { + case 0: + result = operands.Sum(x => x); + break; + + case 1: + result = operands.Aggregate(1L, (agg, x) => x * agg); + break; + + case 2: + result = operands.Min(x => x); + break; + + case 3: + result = operands.Max(x => x); + break; + + case 4: + throw new Exception(); + + case 5: + System.Diagnostics.Debug.Assert(operands.Count == 2); + result = operands[0] > operands[1] ? 1 : 0; + break; + + case 6: + System.Diagnostics.Debug.Assert(operands.Count == 2); + result = operands[0] < operands[1] ? 1 : 0; + break; + + case 7: + System.Diagnostics.Debug.Assert(operands.Count == 2); + result = operands[0] == operands[1] ? 1 : 0; + break; + + default: + throw new Exception(); + } + + return (versionTotal, result); + } +} diff --git a/src/main.cs b/src/main.cs index 373b828..592466d 100644 --- a/src/main.cs +++ b/src/main.cs @@ -33,7 +33,8 @@ else "12" => new Day12(), "13" => new Day13(), "14" => new Day14(), - _ => new Day15(), + "15" => new Day15(), + _ => new Day16(), }; day.Go(); }