private void SolveRecurse(Int32 index) { if (Equals(Root, Root.Right)) { HandleSolution(_solutionsRows); // No more columns, we found one solution. } else { DancingColumn nextCol = NextColumn(); // Select next column using some selection algorithm. CoverColumn(nextCol); // Exclude selected column from the matrix. DancingNode row = nextCol.Lower; // Try for each row in selected column. while (Equals(row, nextCol) == false) { _solutionsRows[index] = row; // Add row to solutions array. DancingNode col = row.Right; // Exclude all columns covered by this row while (Equals(col, row) == false) { CoverColumn(col.Header); col = col.Right; } SolveRecurse(index + 1); // And try to solve the reduced matrix. col = row.Left; // Now, restore all columns covered by this row. while (Equals(col, row) == false) { UncoverColumn(col.Header); col = col.Left; } _solutionsRows[index] = null; // And remove row from solution array. row = row.Lower; } UncoverColumn(nextCol); // Return excluded column back to list. } }
internal SudokuArena(Int32[,] puzzle, Int32 boxRows, Int32 boxCols) : base(puzzle.Length * 4) { Solutions = 0; Size = puzzle.GetLength(0); Int32[] positions = new Int32[4]; List <DancingNode> known = new List <DancingNode>(); for (Int32 row = 0; row < Size; row++) { for (Int32 col = 0; col < Size; col++) { Int32 boxRow = row / boxRows; Int32 boxCol = col / boxCols; for (Int32 digit = 0; digit < Size; digit++) { bool isGiven = (puzzle[row, col] == (digit + 1)); positions[0] = 1 + (row * Size + col); positions[1] = 1 + puzzle.Length + (row * Size + digit); positions[2] = 1 + 2 * puzzle.Length + (col * Size + digit); positions[3] = 1 + 3 * puzzle.Length + ((boxRow * boxRows + boxCol) * Size + digit); DancingNode newRow = AddRow(positions); if (isGiven) { known.Add(newRow); } } } } RemoveKnown(known); }
private static string Name(DancingNode node) { if (node == null) { return("NULL"); } return(node.Name()); }
internal void AddNode(DancingNode node) { DancingNode last = this.Upper; node.Upper = last; node.Lower = this; last.Lower = node; this.Upper = node; IncRows(); }
internal DancingNode AddRow(Int32[] positions) { DancingNode result = null; if (positions.Length > 0) { bool found; DancingNode thisNode = null; DancingNode prevNode = null; Rows++; for (Int32 i = 0; i < positions.Length; i++) { if (positions[i] > 0) { thisNode = new DancingNode(Rows, positions[i]); thisNode.Left = prevNode; thisNode.Right = null; if (prevNode != null) { prevNode.Right = thisNode; } else { result = thisNode; } found = false; for (Int32 j = 0; j < _headerColumns.Length; j++) { DancingColumn col = _headerColumns[j]; if (col.Col == positions[i]) { thisNode.Header = col; col.AddNode(thisNode); found = true; } } if (!found) { Debug.WriteLine("Can't find header for {0}.", positions[i]); } prevNode = thisNode; result.Left = prevNode; prevNode.Right = result; } } } return(result); }
internal void ShowState() { DancingColumn col = FirstColumn; while (Equals(col, Root) == false) { Debug.WriteLine("C : {0}", col.ToString()); DancingNode row = col.Lower; while (Equals(row, col) == false) { Debug.WriteLine(" R : {0}", row.ToString()); row = row.Lower; } col = (DancingColumn)col.Right; } }
internal void RemoveKnown(List <DancingNode> solutions) { for (Int32 i = 0; i < solutions.Count; i++) { DancingNode row = solutions[i]; _solutionsRows[Initial] = row; Initial++; CoverColumn(row.Header); DancingNode col = row.Right; while (Equals(col, row) == false) { CoverColumn(col.Header); col = col.Right; } } }
private void UncoverColumn(DancingColumn column) { DancingNode row = column.Upper; while (Equals(row, column) == false) { DancingNode col = row.Left; while (Equals(col, row) == false) { col.Upper.Lower = col; col.Lower.Upper = col; col.Header.IncRows(); col = col.Left; } row = row.Upper; } column.Left.Right = column; column.Right.Left = column; }