public virtual void Solve() { DancingLinks <Sudoku.ColumnName> model = MakeModel(); int results = model.Solve(new Sudoku.SolutionPrinter(size)); System.Console.Out.WriteLine("Found " + results + " solutions"); }
/// <summary> /// For a given piece, generate all of the potential placements and add them /// as rows to the model. /// </summary> /// <param name="dancer">the problem model</param> /// <param name="piece">the piece we are trying to place</param> /// <param name="width">the width of the board</param> /// <param name="height">the height of the board</param> /// <param name="flip">is the piece flipped over?</param> /// <param name="row">a workspace the length of the each row in the table</param> /// <param name="upperLeft"> /// is the piece constrained to the upper left of the board? /// this is used on a single piece to eliminate most of the trivial /// roations of the solution. /// </param> private static void GenerateRows(DancingLinks dancer, Pentomino.Piece piece, int width, int height, bool flip, bool[] row, bool upperLeft) { // for each rotation int[] rotations = piece.GetRotations(); for (int rotIndex = 0; rotIndex < rotations.Length; ++rotIndex) { // get the shape bool[][] shape = piece.GetShape(flip, rotations[rotIndex]); // find all of the valid offsets for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { if (y + shape.Length <= height && x + shape[0].Length <= width && (!upperLeft || (IsSide(x, shape[0].Length, width) && IsSide(y, shape.Length, height)))) { // clear the columns related to the points on the board for (int idx = 0; idx < width * height; ++idx) { row[idx] = false; } // mark the shape for (int subY = 0; subY < shape.Length; ++subY) { for (int subX = 0; subX < shape[0].Length; ++subX) { row[(y + subY) * width + x + subX] = shape[subY][subX]; } } dancer.AddRow(row); } } } } }
private DancingLinks <Sudoku.ColumnName> MakeModel() { DancingLinks <Sudoku.ColumnName> model = new DancingLinks <Sudoku.ColumnName>(); // create all of the columns constraints for (int x = 0; x < size; ++x) { for (int num = 1; num <= size; ++num) { model.AddColumn(new Sudoku.ColumnConstraint(num, x)); } } // create all of the row constraints for (int y = 0; y < size; ++y) { for (int num = 1; num <= size; ++num) { model.AddColumn(new Sudoku.RowConstraint(num, y)); } } // create the square constraints for (int x_1 = 0; x_1 < squareYSize; ++x_1) { for (int y_1 = 0; y_1 < squareXSize; ++y_1) { for (int num = 1; num <= size; ++num) { model.AddColumn(new Sudoku.SquareConstraint(num, x_1, y_1)); } } } // create the cell constraints for (int x_2 = 0; x_2 < size; ++x_2) { for (int y_1 = 0; y_1 < size; ++y_1) { model.AddColumn(new Sudoku.CellConstraint(x_2, y_1)); } } bool[] rowValues = new bool[size * size * 4]; for (int x_3 = 0; x_3 < size; ++x_3) { for (int y_1 = 0; y_1 < size; ++y_1) { if (board[y_1][x_3] == -1) { // try each possible value in the cell for (int num = 1; num <= size; ++num) { model.AddRow(GenerateRow(rowValues, x_3, y_1, num)); } } else { // put the given cell in place model.AddRow(GenerateRow(rowValues, x_3, y_1, board[y_1][x_3])); } } } return(model); }