Exemple #1
0
    public void Solve(ReadOnlySpan <byte> input, Solution solution)
    {
        bool[,] pixels = new bool[50, 6];

        bool[] rowBuffer = new bool[50];
        bool[] colBuffer = new bool[6];
        foreach (ReadOnlySpan <byte> line in input.SplitLines())
        {
            if (line[1] == 'e') // rect
            {
                var reader = new SpanReader(line.Slice("rect ".Length));
                int width  = reader.ReadPosIntUntil('x');
                int height = reader.ReadPosIntUntilEnd();
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        pixels[x, y] = true;
                    }
                }
            }
            else if (line[7] == 'c') // rotate column
            {
                var reader = new SpanReader(line.Slice("rotate column x=".Length));
                int column = reader.ReadPosIntUntil(' ');
                reader.SkipLength("by ".Length);
                int rotateAmount = reader.ReadPosIntUntilEnd();

                for (int i = 0; i < 6; i++)
                {
                    colBuffer[i] = pixels[column, i];
                    int target = i - rotateAmount;
                    if (target < 0)
                    {
                        target += 6;
                    }

                    // if the target has already been swapped, get it from the buffer
                    pixels[column, i] = target < i ? colBuffer[target] : pixels[column, target];
                }
            }
            else // rotate row
            {
                var reader = new SpanReader(line.Slice("rotate row y=".Length));
                int row    = reader.Peek() - '0';
                reader.SkipLength("0 by ".Length);
                int rotateAmount = reader.ReadPosIntUntilEnd();

                for (int i = 0; i < 50; i++)
                {
                    rowBuffer[i] = pixels[i, row];
                    int target = i - rotateAmount;
                    if (target < 0)
                    {
                        target += 50;
                    }

                    // if the target has already been swapped, get it from the buffer
                    pixels[i, row] = target < i ? rowBuffer[target] : pixels[target, row];
                }
            }
        }

        int part1 = 0;

        foreach (bool pixel in pixels)
        {
            if (pixel)
            {
                part1++;
            }
        }

        Span <char> part2 = stackalloc char[10];

        for (int i = 0; i < 10; i++)
        {
            int letterPixels = 0;
            for (int row = 0; row < 6; row++)
            {
                for (int col = 0; col < 5; col++)
                {
                    if (pixels[i * 5 + col, row])
                    {
                        letterPixels |= 1 << (29 - (row * 5 + col));
                    }
                }
            }

            part2[i] = OCR.MaskToLetter(letterPixels);
        }

        solution.SubmitPart1(part1);
        solution.SubmitPart2(part2);
    }
Exemple #2
0
    public void Solve(ReadOnlySpan <byte> input, Solution solution)
    {
        int foldsIndex = input.IndexOf((byte)'f');
        ReadOnlySpan <byte> foldsInput = input.Slice(foldsIndex);
        ReadOnlySpan <byte> dotsInput  = input.Slice(0, foldsIndex - 1);

        Span <int> xFolds = stackalloc int[32];
        Span <int> yFolds = stackalloc int[32];

        ParseFolds(foldsInput, xFolds, yFolds, out int numXFolds, out int numYFolds, out bool firstFoldIsX);

        var firstFoldAxis = firstFoldIsX ? xFolds[0] : yFolds[0];

        int maxX = xFolds[0] * 2 + 1;
        int maxY = yFolds[0] * 2 + 1;

        Span <byte> finalXPositions = stackalloc byte[maxX + 1];
        Span <byte> finalYPositions = stackalloc byte[maxY + 1];

        for (byte x = 0; x < 40; x++)
        {
            finalXPositions[x] = x;
        }

        for (int i = numXFolds - 1; i >= 0; i--)
        {
            int fold = xFolds[i];
            var dst  = finalXPositions.Slice(fold + 1, fold);
            finalXPositions.Slice(0, fold).CopyTo(dst);
            dst.Reverse();
        }

        for (byte y = 0; y < 6; y++)
        {
            finalYPositions[y] = y;
        }

        for (int i = numYFolds - 1; i >= 0; i--)
        {
            int fold = yFolds[i];
            var dst  = finalYPositions.Slice(fold + 1, fold);
            finalYPositions.Slice(0, fold).CopyTo(dst);
            dst.Reverse();
        }

        Span <int> letterMasks      = stackalloc int[8];
        var        dotsAfterOneFold = new HashSet <int>();

        int dotsInputCursor = 0;

        while (dotsInputCursor < dotsInput.Length)
        {
            ParseDot(dotsInput, ref dotsInputCursor, out int x, out int y);

            if (firstFoldIsX)
            {
                if (x > firstFoldAxis)
                {
                    x = 2 * firstFoldAxis - x;
                }
            }
            else
            {
                if (y > firstFoldAxis)
                {
                    y = 2 * firstFoldAxis - y;
                }
            }

            if (dotsAfterOneFold.Add((x << 16) | y))
            {
                x = finalXPositions[x];
                y = finalYPositions[y];

                (int letter, int col) = Math.DivRem(x, 5);

                letterMasks[letter] |= 1 << (29 - (y * 5 + col));
            }
        }

        solution.SubmitPart1(dotsAfterOneFold.Count);

        Span <char> letters = stackalloc char[8];

        for (int i = 0; i < 8; i++)
        {
            letters[i] = OCR.MaskToLetter(letterMasks[i]);
        }

        solution.SubmitPart2(letters);
    }