Last active
December 16, 2021 21:30
-
-
Save thatsumoguy/912ba0de72c4e042ee345f20707d6b16 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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