public void Survival_with_two_living_neighbours()
 {
     var neighbours = Enumerable
         .Range(0, 2)
         .Select(i => new Cell { State = CellState.Alive });
     var cell = new Cell { State = CellState.Alive, Neighbours = neighbours };
     Survival_if_two_or_three_living_neigbours(cell);
 }
 public void Four_living_neighbours_death()
 {
     var neighbours = Enumerable
         .Range(0, 4)
         .Select(i => new Cell { State = CellState.Alive });
     var cell = new Cell { State = CellState.Alive, Neighbours = neighbours };
     More_than_three_living_neigbours_death(cell);
 }
 public void Birth_if_three_living_neighbours()
 {
     var neighbours = Enumerable
         .Range(0, 3)
         .Select(i => new Cell { State = CellState.Alive });
     var cell = new Cell { State = CellState.Dead, Neighbours = neighbours };
     Birth_if_three_living_neighbours(cell);
 }
Пример #4
0
        private bool SolveRecurse(Cell nextCell)
        {
            // Our base case: No more unsolved cells to select, 
            // thus puzzle solved
            if (nextCell.row == -1)
                return true;

            // Loop through all candidates in the cell
            foreach (int candidate in m_cellConstraintMatrix[nextCell.row, nextCell.col])
            {
                writer.WriteLine("{4} -> ({0}, {1}) : {2} ({3})", nextCell.row, nextCell.col,
                    m_cellConstraintMatrix[nextCell.row, nextCell.col], m_cellConstraintMatrix[nextCell.row, nextCell.col].Count, steps++);

                SelectCandidate(nextCell, candidate);

                // Move to the next cell.
                // if it returns false backtrack
                if (SolveRecurse(NextCell()) == false)
                {
                    ++steps;
                    writer.WriteLine("{0} -> BACK", steps);
                    UnselectCandidate(nextCell, candidate);
                    continue;
                }
                else // if we recieve true here this means the puzzle was solved earlier
                    return true; 
            }

            // return false if path is unsolvable
            return false;

        }
Пример #5
0
        private void SelectCandidate(Cell aCell, int candidate)
        {
            HashSet<Cell> changedCells = new HashSet<Cell>();

            // place candidate on grid
            m_grid[aCell.row, aCell.col] = candidate;

            // remove from bucket list
            bucketList[m_cellConstraintMatrix[aCell.row, aCell.col].Count].Remove(aCell);

            // remove candidate from cell constraint matrix
            m_cellConstraintMatrix[aCell.row, aCell.col][candidate] = false;

            // add the candidate to the cell, row, col, region constraint matrices
            m_colConstraintMatrix[aCell.col][candidate] = true;
            m_rowConstraintMatrix[aCell.row][candidate] = true;
            m_regionConstraintMatrix[aCell.row / 3, aCell.col / 3][candidate] = true;

            /**** RIPPLE ACROSS COL, ROW, REGION ****/

            // (propagation)
            // remove candidates across unsolved cells in the same
            // row and col.
            for (int i = 0; i < 9; i++)
            {
                // only change unsolved cells containing the candidate
                if (m_grid[aCell.row, i] == 0)
                {
                    if (m_cellConstraintMatrix[aCell.row, i][candidate] == true)
                    {
                        // shift affected cells down the bucket list
                        bucketList[m_cellConstraintMatrix[aCell.row, i].Count].Remove(new Cell(aCell.row, i));
                        bucketList[m_cellConstraintMatrix[aCell.row, i].Count - 1].Add(new Cell(aCell.row, i));

                        // remove the candidate
                        m_cellConstraintMatrix[aCell.row, i][candidate] = false;

                        //update changed cells (for backtracking)
                        changedCells.Add(new Cell(aCell.row, i));
                    }
                }
                // only change unsolved cells containing the candidate
                if (m_grid[i, aCell.col] == 0)
                {
                    if (m_cellConstraintMatrix[i, aCell.col][candidate] == true)
                    {
                        // shift affected cells down the bucket list
                        bucketList[m_cellConstraintMatrix[i, aCell.col].Count].Remove(new Cell(i, aCell.col));
                        bucketList[m_cellConstraintMatrix[i, aCell.col].Count - 1].Add(new Cell(i, aCell.col));

                        // remove the candidate
                        m_cellConstraintMatrix[i, aCell.col][candidate] = false;

                        //update changed cells (for backtracking)
                        changedCells.Add(new Cell(i, aCell.col));
                    }
                }
            }

            // (propagation)
            // remove candidates across unsolved cells in the same
            // region.
            int grid_row_start = aCell.row / 3 * 3;
            int grid_col_start = aCell.col / 3 * 3;
            for (int row = grid_row_start; row < grid_row_start + 3; row++)
                for (int col = grid_col_start; col < grid_col_start + 3; col++)
                    // only change unsolved cells containing the candidate
                    if (m_grid[row, col] == 0)
                    {
                        if (m_cellConstraintMatrix[row, col][candidate] == true)
                        {
                            // shift affected cells down the bucket list
                            bucketList[m_cellConstraintMatrix[row, col].Count].Remove(new Cell(row, col));
                            bucketList[m_cellConstraintMatrix[row, col].Count - 1].Add(new Cell(row, col));

                            // remove the candidate
                            m_cellConstraintMatrix[row, col][candidate] = false;

                            //update changed cells (for backtracking)
                            changedCells.Add(new Cell(row, col));
                        }
                    }

            // add cell to solved list
            unsolved.Remove(aCell);
            solved.Add(aCell);
            changed.Push(changedCells);
        }
Пример #6
0
        // Backtracking method. Undoes the specified selection
        private void UnselectCandidate(Cell aCell, int candidate)
        {
            // 1) Remove selected candidate from grid
            m_grid[aCell.row, aCell.col] = 0;

            // 2) Add that candidate back to the cell constraint matrix.
            //    Since it wasn't selected, it can still be selected in the 
            //    future
            m_cellConstraintMatrix[aCell.row, aCell.col][candidate] = true;

            // 3) Put cell back in the bucket list
            bucketList[m_cellConstraintMatrix[aCell.row, aCell.col].Count].Add(aCell);

            // 4) Remove the candidate from the row, col, and region constraint matrices
            m_rowConstraintMatrix[aCell.row][candidate] = false;
            m_colConstraintMatrix[aCell.col][candidate] = false;
            m_regionConstraintMatrix[aCell.row / 3, aCell.col / 3][candidate] = false;

            // 5) Add the candidate back to any cells that changed from
            //    its selection (propagation).
            foreach (Cell c in changed.Pop())
            {
                // shift affected cells up the bucket list
                bucketList[m_cellConstraintMatrix[c.row, c.col].Count].Remove(c);
                bucketList[m_cellConstraintMatrix[c.row, c.col].Count + 1].Add(c);
                m_cellConstraintMatrix[c.row, c.col][candidate] = true;
            }

            // 6) Add the cell back to the list of unsolved
            solved.Remove(aCell);
            unsolved.Add(aCell);
        }
Пример #7
0
        private void PopulateCandidates()
        {
            //Add possible candidates by checking
            //the rows, columns and grid
            for (int row = 0; row < 9; row++)
            {
                for (int col = 0; col < 9; col++)
                {
                    //if solved, then there are no possible candidates
                    if (m_grid[row, col] > 0)
                    {
                        m_cellConstraintMatrix[row, col].SetAll(false);
                        solved.Add(new Cell(row, col));
                    }
                    else
                    {
                        // populate each cell with possible candidates
                        // by checking the row, col, and grid associated 
                        // with that cell
                        foreach (int candidate in m_rowConstraintMatrix[row])
                            m_cellConstraintMatrix[row, col][candidate] = false;
                        foreach (int candidate in m_colConstraintMatrix[col])
                            m_cellConstraintMatrix[row, col][candidate] = false;
                        foreach (int candidate in m_regionConstraintMatrix[row / 3, col / 3])
                            m_cellConstraintMatrix[row, col][candidate] = false;

                        Cell c = new Cell(row, col);
                        bucketList[m_cellConstraintMatrix[row, col].Count].Add(c);
                        unsolved.Add(c);
                    }
                }
            }
        }
 public void No_neighbours_death()
 {
     var cell = new Cell { State = CellState.Alive, Neighbours = Enumerable.Empty<ICell>() };
     Less_than_two_neighbours_death(cell);
 }