Exemple #1
0
    private static long ProcessPacket(BinaryString b, List <long> versions)
    {
        long version = b.ReadBits(3);
        long type    = b.ReadBits(3);

        versions.Add(version);

        if (type == 4)
        {
            // Base case. Literals contain no sub packets, so just calculate the value they represent and return
            return(ProcessLiteral(b));
        }

        List <long> subResults = new();

        // Operator case. Determine how to read the sub packets
        long lengthTypeId = b.ReadBits(1);

        if (lengthTypeId == 0)
        {
            // Sub packet section is defined by the number of bits
            long subPacketBitLength = b.ReadBits(15);
            long positionBefore     = b.Position;
            long goalPosition       = positionBefore + subPacketBitLength;
            while (b.Position < goalPosition)
            {
                long subResult = ProcessPacket(b, versions);
                subResults.Add(subResult);
            }
        }
        else if (lengthTypeId == 1)
        {
            // Sub packet section is defined by the number of packets
            long numberOfSubPackets = b.ReadBits(11);
            for (int i = 0; i < numberOfSubPackets; i++)
            {
                long subResult = ProcessPacket(b, versions);
                subResults.Add(subResult);
            }
        }

        // Evaluate the different operators against the sub packet results
        return(type switch
        {
            0 => subResults.Sum(),
            1 => subResults.Aggregate(1L, (acc, x) => acc * x),
            2 => subResults.Min(),
            3 => subResults.Max(),
            5 => subResults[0] > subResults[1] ? 1 : 0,
            6 => subResults[0] < subResults[1] ? 1 : 0,
            7 => subResults[0] == subResults[1] ? 1 : 0,
            _ => throw new NotSupportedException(type.ToString()),
        });