Skip to content

Instantly share code, notes, and snippets.

@thatsumoguy
Last active December 16, 2021 21:30
Show Gist options
  • Save thatsumoguy/912ba0de72c4e042ee345f20707d6b16 to your computer and use it in GitHub Desktop.
Save thatsumoguy/912ba0de72c4e042ee345f20707d6b16 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Linq;
using System.Diagnostics;
namespace AdventOfCode2021
{
class Day16
{
public static (long result, long time) PartOne()
{
var sw = new Stopwatch();
sw.Start();
var bits = ConvertToBits(File.ReadAllText(@"Input.txt"));
var version = 0L;
var (_, _, totalVersion) = ReadPackets(bits, ref version);
sw.Stop();
return (totalVersion, sw.ElapsedMilliseconds);
}
public static (long result, long time) PartTwo()
{
var sw = new Stopwatch();
sw.Start();
var bits = ConvertToBits(File.ReadAllText(@"Input.txt"));
var version = 0L;
var (_, totalResult, _) = ReadPackets(bits, ref version);
sw.Stop();
return (totalResult, sw.ElapsedMilliseconds);
}
private static byte[] ConvertToBits(string lines)
{
var bytes = Enumerable.Range(0, lines.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(lines.Substring(x, 2), 16)).ToArray();
var bits = new byte[bytes.Length * 8];
for(var i = 0; i < bytes.Length; i++)
{
var curr = bytes[i];
var baseNum = 7;
for (var j =0; j < 8; j++)
{
bits[i * 8 + j] = (byte)((curr >> baseNum) & 1);
baseNum--;
}
}
return bits;
}
private static (int totalOffset, long totalResult, long totalVersion) ReadPackets(byte[] bits, ref long totalVersion)
{
var offset = 0;
var version = GetValue(bits.Slice(offset, 3));
offset += 3;
totalVersion += version;
var packetType = GetValue(bits.Slice(offset, 3));
offset += 3;
if(packetType == 4)
{
(long result, int addedOffset) = GetTotalValue(bits[offset..]);
offset += addedOffset;
return (offset, result, totalVersion);
}
var results = new List<long>();
int typeID = bits[offset];
offset++;
if(typeID == 0)
{
var length = GetValue(bits.Slice(offset, 15));
offset += 15;
var totalLengthOffset = 0;
while(totalLengthOffset < length)
{
(int addedOffset, long result, _) = ReadPackets(bits[offset..], ref totalVersion);
offset += addedOffset;
totalLengthOffset += addedOffset;
results.Add(result);
}
}
else if(typeID == 1)
{
var length = GetValue(bits.Slice(offset, 11));
offset += 11;
for(var i = 0; i < length; i++)
{
(int addedOffset, long result, _) = ReadPackets(bits[offset..], ref totalVersion);
offset += addedOffset;
results.Add(result);
}
}
return (offset, GetResult(packetType, results), totalVersion);
}
private static long GetResult(int packetType, List<long> results)
{
return packetType switch
{
0 => results.Sum(),
1 => results.Aggregate(1L, (a, b) => a * b),
2 => results.Min(),
3 => results.Max(),
5 => results[0] > results[1] ? 1L : 0L,
6 => results[0] < results[1] ? 1L : 0L,
7 => results[0] == results[1] ? 1L : 0L,
_ => 0L,
};
}
private static int GetValue(byte[] bits)
{
var result = 0;
foreach (var bit in bits)
{
result = result << 1 | bit;
}
return result;
}
private static (long value, int addedOffset) GetTotalValue(byte[] bits)
{
var offset = 0;
var value = 0L;
bool notZero;
do
{
notZero = bits[offset] == 1;
offset++;
var group = GetValue(bits.Slice(offset, 4));
offset += 4;
value = value << 4 | (uint)group;
} while (notZero);
return (value, offset);
}
}
public static class Helper
{
public static T[] Slice<T>(this T[] bits, int start, int length)
{
var slice = new T[length];
Array.Copy(bits, start, slice, 0, length);
return slice;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment