/// <summary>
        /// Seed the second box.
        ///
        /// This is more difficult, but still quick.
        ///
        /// B2's 1st row can be any from B1's 2nd or 3rd
        /// B2's 2nd row must include any remaining from B2's 3rd row, fill in with B1's 1st row
        /// B2's 3rd row is all remaining
        /// </summary>
        public void SeedSecondBox()
        {
            var boxSize    = PuzzleGrid.Size.BoxSize();
            var puzzleSize = PuzzleGrid.Size.ToInt32();

            var firstBoxUsed = CreateArray(boxSize, () => new PuzzleSet(PuzzleGrid.Size));

            // load first box used values
            foreach (var boxCell in Enumerable.Range(0, puzzleSize))
            {
                var cell      = PuzzleBoxes[0][boxCell];
                var cellValue = cell.Value
                                ?? throw new Exception($"Cell at {cell.Coordinate} is null");

                firstBoxUsed[cell.Coordinate.Row].Add(cellValue);
            }

            var usedByRow = CreateArray(boxSize, () => new PuzzleSet(PuzzleGrid.Size));

            // chose values for first row of second box (from first box, second and third rows)
            var firstRowPossibilities = new PuzzleSet(firstBoxUsed[1]);

            firstRowPossibilities.UnionWith(firstBoxUsed[2]);
            for (var i = 0; i < boxSize; i++)
            {
                var value = PickRandomValueFromPuzzleSet(firstRowPossibilities);

                usedByRow[0].Add(value);
                firstRowPossibilities.Remove(value);
            }

            // chose values for second row of the second box
            var secondRowPossibilities = new PuzzleSet(firstBoxUsed[0]);

            secondRowPossibilities.UnionWith(firstBoxUsed[2]);
            secondRowPossibilities.ExceptWith(usedByRow[0]);

            var thirdRowPossibilities = new PuzzleSet(firstBoxUsed[0]);

            thirdRowPossibilities.UnionWith(firstBoxUsed[1]);
            thirdRowPossibilities.ExceptWith(usedByRow[0]);

            while (thirdRowPossibilities.Count > 3)
            {
                var value = PickRandomValueFromPuzzleSet(secondRowPossibilities);

                usedByRow[1].Add(value);
                secondRowPossibilities.Remove(value);
                thirdRowPossibilities.Remove(value);
            }

            // Value for bottom row
            secondRowPossibilities.ExceptWith(thirdRowPossibilities);

            usedByRow[1].UnionWith(secondRowPossibilities);
            usedByRow[2].UnionWith(thirdRowPossibilities);

            // assign values to each row of the box
            for (var row = 0; row < boxSize; row++)
            {
                for (var col = boxSize; col < 2 * boxSize; col++)
                {
                    var value = PickRandomValueFromPuzzleSet(usedByRow[row]);

                    PuzzleGrid[new PuzzleCoordinate(row, col)] = Convert.ToByte(value);
                    usedByRow[row].Remove(value);
                }
            }
        }