Пример #1
0
        /// <summary>
        ///   Standard constructor
        /// </summary>
        /// <param name = "size">Length of one side of the square</param>
        public SudokuModel(int size)
        {
            // Initialize our variables
            _size = size;
            _sizeSqrt = Convert.ToInt32(Math.Sqrt(size));
            _sizeSquared = size * size;
            _sizeCubed = _sizeSquared * size;
            _possibilitySetModel = (1 << _size) - 1;
            _possibilitySetCell = new int[Size, Size];
            _remainingPossibilityCount = new int[Size, Size];
            _value = new int[Size, Size];
            _lastChangedIterCell = new int[Size, Size];

            // Initialize the Cell objects, and the cache values
            for (var col = 0; col < size; ++col) {
                for (var row = 0; row < size; ++row) {
                    _possibilitySetCell[col, row] = PossibilitySetModel;
                    _remainingPossibilityCount[col, row] = Size;
                    _value[col, row] = -1;
                    _lastChangedIterCell[col, row] = -1;
                    CellChanged = null;
                }
            }
            CellChanged += HandleCellChanged;

            _solved = new int[3, _size];
            _lastChangedIterRegion = new int[3, _size];
            _cellsRegion = new Cell[3, _size][];
            _intersectingRegions = new Region[Size, Size][];
            for (var i = 0; i < _size; ++i) {
                _lastChangedIterRegion[0, i] = -1;
                _lastChangedIterRegion[1, i] = -1;
                _lastChangedIterRegion[2, i] = -1;
                var colCells = new Cell[_size];
                for (var j = 0; j < _size; ++j) {
                    colCells[j] = new Cell(i, j);
                }
                _cellsRegion[(int)RegionType.Column, i] = colCells;
                var rowCells = new Cell[_size];
                for (var j = 0; j < _size; ++j) {
                    rowCells[j] = new Cell(j, i);
                }
                _cellsRegion[(int)RegionType.Row, i] = rowCells;
                var sqCells = new Cell[_size];
                var sqrCol = i % _sizeSqrt;
                var sqrRow = i / _sizeSqrt;
                var startCol = sqrCol * _sizeSqrt;
                var startRow = sqrRow * _sizeSqrt;
                for (var c = 0; c < _sizeSqrt; ++c) {
                    for (var r = 0; r < _sizeSqrt; ++r) {
                        sqCells[r * _sizeSqrt + c] = new Cell(c + startCol, r + startRow);
                    }
                }
                _cellsRegion[(int)RegionType.Square, i] = sqCells;
            }
        }
Пример #2
0
        public Cell[][] GetCellsMatrix()
        {
            Cell[][] matrix = new Cell[rows][];

            int row = rows;
            while (row-- > 0)
            {
                matrix[row] = new Cell[columns];
                int column = columns;
                while (column-- > 0)
                    matrix[row][column] = cells[row][column];
            }

            return matrix;
        }
Пример #3
0
        public SubGrid(int columns, int rows, int column, int row)
        {
            this.columns = rows;                                                                    // Swop columns and rows values
            this.rows = columns;
            Column = column;
            Row = row;

            cells = new Cell[this.rows][];
            for (row = 0; row < this.rows; row++)
            {
                cells[row] = new Cell[this.columns];
                for (column = 0; column < this.columns; column++)
                    cells[row][column] = new Cell(columns, rows, column, row);
            }
        }
Пример #4
0
        private Cell[][] GetTransposedCellsMatrix()                                                 // Get state of current grid - returned as a transposed n*m matrix (not separated by sub grids)
        {
            int subGridColumn = columns;
            int matrixColumn = subGridColumn * rows;                                                // Use SubGrid's number of rows i.e. swopped columns
            Cell[][] matrix = new Cell[matrixColumn][];

            int subGridRows = rows;
            int matrixRows = subGridRows * columns;
            while (matrixColumn-- > 0)
                matrix[matrixColumn] = new Cell[matrixRows];

            while (subGridColumn-- > 0)
            {
                int subGridRow = subGridRows;
                while (subGridRow-- > 0)
                {
                    var subMatrix = subGrids[subGridRow][subGridColumn].GetCellsMatrix();

                    int cellRow = columns;
                    while (cellRow-- > 0)
                    {
                        int cellColumn = rows;
                        while (cellColumn-- > 0)
                            matrix[subGridColumn * rows + cellColumn][subGridRow * columns + cellRow] = subMatrix[cellRow][cellColumn];
                    }
                }
            }

            return matrix;
        }
Пример #5
0
        private List<LimitedOption> FindOptionsLimitedToMatrix(Cell[][] cells)
        {
            List<LimitedOption> limitedOptions = new List<LimitedOption>();

            for (int index = 0; index < columns * rows; index++)
            {
                IEnumerable<Cell> unsetCells = cells[index].Where(x => !x.IsSet);                   // Get cells that are still to be set
                int totalUnsetCells = unsetCells.Count();

                bool found = false;
                int pick = 1;
                int maxRemainingOptions = unsetCells.Where(x => x.TotalOptionsRemaining < totalUnsetCells).Max(x => (int?)x.TotalOptionsRemaining) ?? 0;    // Max < totalUnsetCells
                while (!found && pick++ < maxRemainingOptions)
                {
                    IEnumerable<Cell> options = unsetCells.Where(x => x.TotalOptionsRemaining <= pick); // Get options with at least the number of bits to pick set
                    var enumerator = combinations.Select(options, pick).GetEnumerator();            // Get enumerator to each combination of options to select, based on the number of items to pick
                    while (!found && enumerator.MoveNext())
                    {
                        int removeOptions = BitUtilities.BitwiseOR(enumerator.Current.Select(x => x.Options));
                        if (found = BitUtilities.NumberOfBitsSet(removeOptions) <= pick)
                            limitedOptions.Add(new LimitedOption { Column = index, Row = index, Options = removeOptions });
                    }
                }
            }

            return limitedOptions;
        }
Пример #6
0
        private Cell[] GetCellsArray()
        {
            Cell[] array = new Cell[columns * rows * columns * rows];

            int subGridRow = rows;
            while (subGridRow-- > 0)
            {
                int subGridColumn = columns;
                while (subGridColumn-- > 0)
                {
                    var subMatrix = subGrids[subGridRow][subGridColumn].GetCellsMatrix();

                    int cellColumn = rows;
                    while (cellColumn-- > 0)
                    {
                        int cellRow = columns;
                        while (cellRow-- > 0)
                            array[(subGridRow * columns + cellRow) * columns * rows + subGridColumn * rows + cellColumn] = subMatrix[cellRow][cellColumn];
                    }
                }
            }

            return array;
        }
Пример #7
0
        public Cell[] Save()
        {
            int size = columns * rows;
            Cell[] cells = new Cell[size * size];

            for (int subGridRow = 0; subGridRow < rows; subGridRow++)
                for (int subGridColumn = 0; subGridColumn < columns; subGridColumn++)
                {
                    var subMatrix = subGrids[subGridRow][subGridColumn].GetCellsMatrix();
                    for (int cellRow = 0; cellRow < columns; cellRow++)
                        for (int cellColumn = 0; cellColumn < rows; cellColumn++)
                            cells[subGridRow * size * columns + subGridColumn * rows + cellRow * size + cellColumn] = new Cell(subMatrix[cellRow][cellColumn]);
                }

            return cells;
        }
Пример #8
0
        private void Load(Cell[] cells)
        {
            Cell[][] subGrid = new Cell[columns][];
            for (int row = 0; row < columns; row++)                                                 // Use SubGrid's number of rows i.e. swopped columns
                subGrid[row] = new Cell[rows];

            int size = columns * rows;

            for (int subGridRow = 0; subGridRow < rows; subGridRow++)
                for (int subGridColumn = 0; subGridColumn < columns; subGridColumn++)
                {
                    for (int cellRow = 0; cellRow < columns; cellRow++)
                        for (int cellColumn = 0; cellColumn < rows; cellColumn++)
                            subGrid[cellRow][cellColumn] = new Cell(cells[subGridRow * size * columns + subGridColumn * rows + cellRow * size + cellColumn]);

                    subGrids[subGridRow][subGridColumn].SetCells(subGrid);
                }
        }
Пример #9
0
        private bool MatrixValid(Cell[][] matrix)
        {
            bool valid = true;
            int size = columns * rows;
            int index = size;
            while (valid && index-- > 0)
            {
                var setOptions = matrix[index].Where(x => x.IsSet).GroupBy(x => x.Options).Where(x => x.Count() == 1).Select(x => x.Key);   // Get unique set cells
                var unsetOptions = matrix[index].Where(x => !x.IsSet).Select(x => x.Options);

                valid = setOptions.Count() + unsetOptions.Count() == size &&                        // Ensures setOptions did not contain duplicates
                    (BitUtilities.BitwiseOR(setOptions) | BitUtilities.BitwiseOR(unsetOptions)) == (1 << size) - 1; // totalSetOptions | totalUnsetOptions must contain all the options
            }

            return valid;
        }
Пример #10
0
 public void SetCells(Cell[][] subGrid)
 {
     for (int row = 0; row < rows; row++)
         for (int column = 0; column < columns; column++)
             cells[row][column] = subGrid[row][column];
 }
Пример #11
0
 /// <summary>
 ///   We update our cache variables and bubble up the event.
 /// </summary>
 void HandleCellChanged(int col, int row, RegionType? foundInType, int foundInI)
 {
     EliminatedCount += 1;
     LastChangedCell = new Cell(col, row);
     var value = _value[col, row];
     foreach (var region in GetIntersectingRegions(col, row)) {
         SetLastChangedIterRegion(region.Type, region.I, ChangeCount);
         if (value != -1) {
             SetValueSolved(region.Type, region.I, value);
         }
     }
     ++ChangeCount;
     if (value != -1) {
         ++SolvedCount;
         if (foundInType.HasValue) {
             DuplicateElimination.EliminateDuplicates(this, col, row, foundInType.Value, foundInI);
         } else {
             DuplicateElimination.EliminateDuplicates(this, col, row);
         }
     }
     if (ModelChanged != null) {
         ModelChanged(col, row);
     }
 }
Пример #12
0
 public bool Contains(RegionType type, int i, Cell cell)
 {
     switch (type) {
         case RegionType.Column:
             return cell.Column == i;
         case RegionType.Row:
             return cell.Row == i;
         case RegionType.Square:
             var sqrCol = i % _sizeSqrt;
             var sqrRow = i / _sizeSqrt;
             var startCol = sqrCol * _sizeSqrt;
             var startRow = sqrRow * _sizeSqrt;
             return (cell.Column >= startCol && cell.Column < startCol + _sizeSqrt &&
                     cell.Row >= startRow && cell.Row < startRow + _sizeSqrt);
     }
     throw new InvalidOperationException();
 }