89 lines
2.5 KiB
C#
89 lines
2.5 KiB
C#
// #define Day16
|
|
#if Day16
|
|
var line = File.ReadAllText("day16/input");
|
|
Console.WriteLine(line);
|
|
|
|
// line = "8A004A801A8002F478";
|
|
|
|
string binarystring = String.Join(String.Empty,
|
|
line.Where(c => !Char.IsWhiteSpace(c)).Select(
|
|
c => Convert.ToString(Convert.ToInt32(c.ToString(), 16), 2).PadLeft(4, '0')
|
|
)
|
|
);
|
|
Console.WriteLine(binarystring);
|
|
|
|
int pos = 0;
|
|
long versionSum = 0;
|
|
Console.WriteLine(ParsePackage(ref pos, binarystring));
|
|
|
|
Console.WriteLine(versionSum);
|
|
|
|
long ParsePackage(ref int pos, string binary) {
|
|
var version = ParseTypeOrVersionId(ref pos, binary);
|
|
versionSum += version;
|
|
var type = ParseTypeOrVersionId(ref pos, binary);
|
|
|
|
if (type == 4) {
|
|
return ParseLiteral(ref pos, binary);
|
|
} else {
|
|
var lengthTypeId = ParseLength(ref pos, binary, 1);
|
|
if (lengthTypeId == 1) {
|
|
return ParseOperatorType1(ref pos, binary, type);
|
|
} else {
|
|
return ParseOperatorType0(ref pos, binary, type);
|
|
}
|
|
}
|
|
}
|
|
|
|
long ParseTypeOrVersionId(ref int pos, string binary) {
|
|
return ParseLength(ref pos, binary, 3);
|
|
}
|
|
|
|
long ParseLiteral(ref int pos, string binary) {
|
|
string res = String.Empty;
|
|
while (binary[pos] == '1') {
|
|
res += binary.Substring(pos + 1, 4);
|
|
pos += 5;
|
|
}
|
|
res += binary.Substring(pos + 1, 4);
|
|
pos += 5;
|
|
return Convert.ToInt64(res, 2);
|
|
}
|
|
|
|
long ParseLength(ref int pos, string binary, int length) {
|
|
var id = binary.Substring(pos, length);
|
|
pos += length;
|
|
return Convert.ToInt64(id, 2);
|
|
}
|
|
|
|
long ParseOperatorType0(ref int pos, string binary, long type) {
|
|
long length = ParseLength(ref pos, binary, 15);
|
|
long originalPos = pos;
|
|
List<long> values = new List<long>();
|
|
while (originalPos+length > pos) {
|
|
values.Add(ParsePackage(ref pos, binary));
|
|
}
|
|
return Calculate(type, values);
|
|
}
|
|
|
|
long ParseOperatorType1(ref int pos, string binary, long type) {
|
|
long numberOfSubPackages = ParseLength(ref pos, binary, 11);
|
|
List<long> values = new List<long>();
|
|
for (int i = 0; i < numberOfSubPackages; i++) {
|
|
values.Add(ParsePackage(ref pos, binary));
|
|
}
|
|
return Calculate(type, values);
|
|
}
|
|
|
|
long Calculate(long type, List<long> values) => (type) switch {
|
|
0 => values.Sum(),
|
|
1 => values.Aggregate(1L, (acc, val) => acc * val),
|
|
2 => values.Min(),
|
|
3 => values.Max(),
|
|
5 => values[0] > values[1] ? 1 : 0,
|
|
6 => values[0] < values[1] ? 1 : 0,
|
|
7 => values[0] == values[1] ? 1 : 0,
|
|
_ => throw new ArgumentException("not defined")
|
|
};
|
|
#endif
|