I'm trying to solve a 9x9 sudoku puzzle using Simulated Annealing, but my implementation doesn't seem to be working correctly. It does not even get closer to a lower-cost solution but instead keeps circling around results that cost between 60 and 80.
My cost function returns the sum of three things: Number of repeating digits in each row, column and block (3x3).
And the successor (neighbour) function i implemented changes two randomly selected digits from the 9x9 grid with random values.
And here is my SA function that doesn't work as expected:
public static void simulatedAnnealing() {
Sudoku neighbour; // candidate successor object
final Double temperature = 2.0; // initial temperature
final Double coolingFactor = 0.999; // cooling constant
final int maxIterations = 1000; // number of iterations
for(Double t = temperature; t>1; t*=coolingFactor) {
for(int i = 0; i < maxIterations; i++) {
neighbour = sudoku.generateSuccessor(); // set random neighbour
int delta = neighbour.cost() - sudoku.cost(); // calculate delta
if (delta <= 0) {
sudoku = neighbour; // always accept good step.
} else {
if (Math.exp(-delta / temperature) > Math.random()) { // Simulated annealing
sudoku = neighbour;
}
}
}
System.out.println(sudoku.cost());
if(sudoku.cost() == 0) { break; } // if puzzle is solved
} }
Function for generating successors:
public Sudoku generateSuccessor() {
int[][] newGrid = new int[9][9];
for(int o = 0; o < 9; o ++) { // cloning current grid array
for(int g = 0; g < 9; g ++) {
newGrid[o][g] = grid[o][g];
}
}
Sudoku rndm = new Sudoku(newGrid); // random Sudoku object.
for (int i = 0; i < 2; i++) { // will randomize 2 cells in 9x9 grid.
int rndmCell = rndmValue(); // random digit for randomizing.
int randomRow = rndm(); // random row that will be randomized
int randomCol = rndm(); // random column that will be randomized
// prevent randomizing given cells in sudoku (in problem definition)
boolean shouldContinue = false;
for (Coordinate c : SudokuSolver.concreteCoordinates) {
if (c.row == randomRow && c.col == randomCol) {
shouldContinue = true;
break;
}
}
if (shouldContinue) {
i--;
continue;
}
// prevention end.
rndm.grid[randomRow][randomCol] = rndmCell;
}
return rndm;
}
Cost function:
public int cost() {
if(hasZeros()) { // if grid is not totally filled with numbers don't calculate its cost.
return -1;
}
int cost = 0;
for(int i = 0; i< 9; i++) { // find total collusions in rows&columns.
cost += findNumberOfCollusions(grid[i]); // find collustions at row 'i'.
cost += findNumberOfCollusions(getColumn(grid,i)); // find collustions at column 'i'.
}
for(int r = 0; r < 9; r += 3) { //find total colusions in blocks (3x3).
for(int c = 0; c < 9; c += 3) {
int[] block = new int[9];
int ctr = 0;
for (int i = r; i < r + 3; i++) {
for (int y = c; y < c+ 3; y++) {
block[ctr] = grid[i][y];
ctr++;
}
}
cost += findNumberOfCollusions(block);
}
}
return cost;
}
When i run the program the output is costs between 60 and 80. After that the temperature goes below the limit and the program outputs a solution that costs around that interval. Can anyone tell me what am i doing wrong? Thanks in advance.
I also had a similar problem to the one you describe, my fitness remained stuck (actually though, my problem was with not copying lists in Python). I can't really assure why your code gets stuck, but if I had to guess: the neighbor generation (int rndmCell = rndmValue(); int randomRow = rndm(); int randomCol = rndm();) may be actually doing more harm than good. Imagine that you have a nearly complete sudoku, but out of the blue two of the correct cells that you had now change their value to a complete opposite one, which is not only wrong on the cell itself but also on the row, column and/or 3x3 square. I'm no mathematician, but logic tells me that the more fitting the sudoku is (i.e. the closer its fitness is to 0), the more chances there are to mess up the sudoku by randomly changing cells. This approach may get you stuck on a local minimum easily.
A more "informed" solution for this problem would be to keep one of the three basic restrictions of the sudoku puzzle fixed by, for instance, generating rows that are permutations of the values [1..9], swapping two cells of a random row (thus still fulfilling the restriction), and calculating the fitness only on the columns and on the 3x3 squares. This choice of neighbor generation is usually more effective. If you are interested, this idea comes from the paper Metaheuristics can solve Sudoku puzzles. I can say that this idea helped me a lot and now the algorithm completes sudokus that I provide :)
Related
I have an assignment for a JAVA class I am taking. We are discussing two-dimensional arrays, however on this particular assignment, I can not figure out how to return back specific points and set those points with a specific value. Here is the assignment:
Write a method called create2DArray that will fill, create, and return
a 10 x 10 2d array with random numbers in the range of 1 to 100. Write
a method called print2DArray that will print a 10 x 10 2D array in row
column fashion. Write a method called createCoords that will search
the 2D array looking for any value that is evenly divisible by 3.
Once you have found a number you should log the row, column location.
This means when your method finishes it should produce a list of
coordinates that I can use to plot my graph. This method must also
return the number of coordinates that are divisible by 3 so that I
know how many points there are to plot. I am not particular as to how
the coordinates are returned back as long as I get a list of the row,
column locations. So, I will leave it to you to work out a mechanism
for returning the values. To test that you have logged the
coordinates create another function called fillLocations that will
fill the locations in the array you have logged with
-1. So, your program should flow in this order
create2DArray
print2DArray
createCoords
fillLocations
print2DArray
I understand and have completed create2DArray and print2DArray, but I can not figure out createCoords and fillLocations. Here is what I have so far, but it does not work and there are errors present:
public int createCoords(int row1, int col1){
int[][] coords = new int[row1][col1];
int[][] count = new int[0][0];
int co = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(coords[row][col] % 3 == 0)
co++;
return count[row][col];
}
}
return co;}
public int fillLocations(int[][] count){
int x = 0;
int y = 0;
for(int row = 0; row < 10; row++)
{
for(int col = 0; col < 10; col++)
{
if(count[row][col] % 3 == 0)
x = row;
y = col;
break;
}
}
return (x, y);}
As a programmer you'll nearly always need to research for doing different things. This research will be easier when you divide your problem to smaller problems.
For example you need to generate random numbers? So search on google that and you'll find this: How do I generate random integers within a specific range in Java?.
You need to create and return a 2D array? Google and see Syntax for creating a two-dimensional array
And with your art, put the pieces of the puzzle together in a way that gives your desired result.
public int[][] create2DArray() {
int[][] newArray = new int[10][10];
Random random = new Random();
int range = 100;
for(int i = 0; i < 10; i++)
{
for(int j = 0;j<arr[0].length;j++)
{
newArray[i][j]= (random.nextInt(range) + 1);
}
}
return newArray;
}
This method, creates and returns a 10*10 2D array filled with random generated numbers between 1-100. I'm sure you can write the rest of your program and enjoy from it by yourself.
Hey guys I'm writing a program for homework to display the path of a ball in a Galton box
My program so far picks how many balls you want to drop, and the amount of slots at the bottom of the box, and the shows you the random path the ball takes.
The problem I've run into is creating a histogram that depicts the end result.
One important piece of information that I found out, is that every time the ball falls to the right, it moves over one position. So if the print statement is LRLRLR it would be in the 3rd slot because of the 3 R's.
An example of a random histogram it could print:
public class Set_8_P6_21 {
public static void main(String[] args) {
// Declaring variables and calling scanner
int balls, slots;
System.out.println("Enter the amount of balls to drop: ");
Scanner input = new Scanner(System.in);
balls = input.nextInt();
System.out.println("Enter the amount of slots: ");
slots = input.nextInt();
char[] arrayslot = new char[slots-1];
int[] arraypattern = new int[slots-1];
// Nested loop that runs the amount of balls through the machine, and through the amount of slots.
for (int i = 0; i < balls; i++) {
System.out.println();
for (int j = 0; j < slots-1; j++) {
double k = Math.random();
if (k < 0.5) {
arrayslot[j] = 'L' ;
arraypattern[j] = 1; // This is where I am trying to make my histogram
}
else if (k >= 0.5) {
arrayslot[j] = 'R';
arraypattern[j] = 0; // This is where I am trying to make my histogram
}
System.out.print(arrayslot[j]);
}
}}}
If anyone has an idea of how could make this print with the information coming from the loop it would be very helpful, thank you for taking your time to read this.
First, there is no real need for you to keep the array arrayslot, because you print the array element right away, and you don't do anything with it afterwards. So you can just print the character:
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
}
As you notice, there is also no need for an else if. Either k is less than 0.5, or it is greater than it. So you can just use else.
In order to figure out which slot the ball will fall into, you need to count the Rs. To do so, you simply have an int that gets 0 at the beginning of each ball's simulation, and then you add to it when you roll an "R" above. So your loop expands to:
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
System.out.println();
}
But of course, if we just do that, the value doesn't go anywhere and we lose it after we finish simulating the ball. What you want to do is keep an array which keeps the number of times we hit each slot. So at the end of each ball's simulation, when we know which slot it fell into, we add 1 to the given slot. If we hit the same slot 3 times, we'll have 3 in that spot in the array:
int[] frequencies = new int[slots];
// Nested loop that runs the amount of balls through the machine, and
// through the amount of slots.
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
frequencies[ballSlot]++;
System.out.println();
}
Now, in order to print the histogram properly, you have to start from the tallest column, and work your way down until you reach the "floor" of the histogram, printing an O for every slot that has balls at that frequency. For example, if we have 3 balls in slots 4 and 5, and 1 ball in slot 2, you start from 3, the highest frequency:
For frequency 3, print O in the 4th and 5th positions.
For frequency 2, no new positions at this height, but you have to print O in 4th and 5th again, because otherwise you'll have an O only at the top of the column, instead of its whole height.
For frequency 1, you print O in the 2nd, 4th and 5th positions.
So in order to do this, we have to find out which is the highest frequency first. You can scan the array for that, but actually, you could calculate it while doing the simulations already:
int[] frequencies = new int[slots];
int maxFrequency = 0;
// Nested loop that runs the amount of balls through the machine, and
// through the amount of slots.
for (int i = 0; i < balls; i++) {
int ballSlot = 0;
for (int j = 0; j < slots - 1; j++) {
double k = Math.random();
if ( k < 0.5 ) {
System.out.print("L");
} else {
System.out.print("R");
ballSlot++;
}
}
frequencies[ballSlot]++;
if ( frequencies[ballSlot] > maxFrequency ) {
maxFrequency = frequencies[ballSlot];
}
System.out.println();
}
As you can see, if any frequency is greater than what we have currently as maxFrequency, we keep it as our new maxFrequency.
Now, the printing of the histogram:
for ( int i = maxFrequency; i > 0; i-- ) {
for ( int j = 0; j < slots; j++ ) {
if ( frequencies[j] >= i ) {
System.out.print( "O");
} else {
System.out.print( " ");
}
}
System.out.println();
}
For each position where we don't have a ball at this level, we print a space. For a position where we have a ball, we print an O.
The variable i represents the current level or height of the histogram we are drawing. So the condition if ( frequencies[j] >= i ) means If at this position, we have at least as many balls as the current height.
That's it. Add a System.out.println() before the simulation loop and before the histogram loop to space between the input, the simulation and the histogram, and you are done.
To this question:
The superqueen is a chess piece that can move like a queen, but also like a knight. What is the maximal number of superqueens on an 8X8 chessboard such that no one can capture an other?
I want to write a brute force algorithm to find the maximum. Here's what I wrote:
public class Main {
public static boolean chess[][];
public static void main(String[] args) throws java.lang.Exception {
chess = new boolean[8][8];
chess[0][0] = true;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
/*Loop to check various possibilities*/
if (!checkrow(i) && !checkcolumn(j) && !checkdiagonals(i, j) && !checkknight(i, j)) {
if (i != 0 || j != 0) {
chess[i][j] = true;
}
}
}
}/*printing the array*/
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.print(((chess[i][j]) ? "T" : "x") + "|");
}
System.out.println();
}
}
/*All working fine here*/
public static boolean checkrow(int a) {
for (int i = 0; i < 8; i++) {
if (chess[a][i]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkcolumn(int a) {
for (int i = 0; i < 8; i++) {
if (chess[i][a]) {
return true;
}
}
return false;
}
/*All working fine here*/
public static boolean checkdiagonals(int pi, int pj) {
int i = pi - Math.min(pi, pj);
int j = pj - Math.min(pi, pj);
for (int k = i, l = j; k < 8 && l < 8; k++, l++) {
if (chess[k][l]) {
return true;
}
}
int i_2 = pi - Math.min(pi, pj);
int j_2 = pj + Math.min(pi, pj);
for (int k = i_2, l = j_2; k < 8 && l > 1; k++, l--) {
if (chess[k][l]) {
return true;
}
}
return false;
}
/*Not All working fine here try commenting out this method above so that that it doesn't run during the check*/
public static boolean checkknight(int pi, int pj) {
for (int i = -1; i <= 1; i++) {
for (int j = -1; j <= 1; j++) {
if (0 <= pi + 2 * i && pi + 2 * i <= 8 && 0 <= pj + j && pj + j <= 8) {
if (chess[pi + 2 * i][pj + j]) {
return true;
}
}
if (0 <= pi + i && pi + i <= 8 && 0 <= pj + 2 * j && pj + 2 * j <= 8) {
if (chess[pi + i][pj + 2 * i]) {
return true;
}
}
}
}
return false;
}
}
I have two questions:
My algorithm for checkknight looks for all knight positions, is it wrong? or there is some coding error.Everything is working fine when I comment out it and I get a nice solution.
Secondly it'll result only in one solution.For other solutions I have to offset(or change position) of other pieces bit by bit after each mega-loop of this, I am confused about implementing it. My instincts guide me that I need to change whole of the code. Is there a modification or a way to do it?
Additional Thoughts: I think we would add to a counter each time we place a piece and add to a long array and output the maximum and array after storing the relevant data.
Code Location: You may view/edit/fork/download it at http://ideone.com/gChD8a
This a rough brute-force method starting from the opposite direction, i.e. from the solved eight-queens puzzle. This will allow us to find a bunch of viable solutions.
The brute-force technique for going from a single superqueen to potentially 8 seems to be especially complex due to the knight's traversal. Based on the runs, about 60% of the viable paths for normal queens are invalid with superqueens. So if we were to instead brute force normal queens, and then work backwards, that is potential time saved for finding a solution, and we can better determine the run-time. Because we know normal queens is easier.
We start off with the 12 fundamental solutions, we would then use these as inputs. Solving normal queens is outside this, but the wiki page has a fantastic article describing everything.
In my case, I stored them as Strings representing the coordinate of the queen (the rows are indices).
So: "17468253" = A1, B7, C4, D6, E8, F2, G5, H3
By brute-forcing the opposite direction from solved queens, we only have to test at most 12 x 8! possible solutions. Because order doesn't matter, additional optimization could occur by eliminating duplicate boards and solutions for processing.
First up, checkKnight, which appears to be your source of confusion. Using absolute values, you can reasonably determine whether or not a piece is within knight's range by checking whether the X offset is 2 and Y offset is 1, or vice versa. You've made a complex checkKnight function to check each individual location and whether or not a piece is on the border. Working the other way by hitscanning each queen to each other queen is logically simpler and less of a nightmare to debug.
Queen class
public class Queen {
int i, j;
public Queen(int i, int j) {
this.i = i;
this.j = j;
}
public boolean checkKnight(Queen queen) { // if any queen meets another
// queen at 2 and 1 offset, we
// eliminate it.
return (Math.abs(i - queen.i) == 2 && Math.abs(j - queen.j) == 1)
|| (Math.abs(i - queen.i) == 1 && Math.abs(j - queen.j) == 2);
}
}
This board has been modified since I originally posted. It takes a String input and converts it to a full chessboard. It has some minor work towards the potential any-size board, but right now it handles child board creation. When a child board is created, the queens are passed by reference rather than making a whole new set of queens. A total of 96 queens are stored in memory, 1 for each one on the original 12-board solution. Not perfectly optimized, but better than 96 -> 672 -> 4032 -> ...
Board class
public class Board {
static int boardSize = 8;
ArrayList<Queen> queens = new ArrayList<Queen>();
public Board(String s) {
for (int i = 0; i < s.length(); i++) {
queens.add(new Queen(i, s.charAt(i) - 49)); // you could implement
// base 16 here, for
// example, for a 15x15
// board
}
}
public Board(Board b) { // duplicates the board, but keeps references to
// queens to conserve memory, only 96 total queens
// in existence through search!
for (Queen q : b.queens) {
queens.add(q);
}
}
public boolean checkForImpact() {
for (int i = 0; i < queens.size(); i++) {
for (int j = i + 1; j < queens.size(); j++) {
if (queens.get(i).checkKnight(queens.get(j))) { // just check
// for any
// queens
// intersecting,
// one hit is
// enough
return true;
}
}
}
return false;
}
public ArrayList<Board> getChildBoards() { // create child boards with a
// single queen removed
ArrayList<Board> boards = new ArrayList<Board>();
for (int i = 0; i < queens.size(); i++) {
boards.add(new Board(this));
}
int i = 0;
for (Board b : boards) {
b.queens.remove(i);
i++;
}
return boards;
}
public String drawBoard() {
String s = "";
char[][] printableBoard = new char[boardSize][boardSize];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
printableBoard[i][j] = '_';
}
}
for (Queen q : queens) {
printableBoard[q.i][q.j] = 'Q';
}
s += " A B C D E F G H\n";
for (int i = 0; i < 8; i++) {
s += (8 - i) + "|";
for (int j = 0; j < boardSize; j++) {
s += printableBoard[i][j];
s += "|";
}
s += "\n";
}
return s;
}
}
Test class
import java.util.ArrayList;
public class Test {
static String[] boards = { "24683175", "17468253", "17582463", "41582736",
"51842736", "31758246", "51468273", "71386425", "51863724",
"57142863", "63184275", "53172864" }; // all 12 solutions for the 8
// queens problem
static ArrayList<Board> boardObjects = new ArrayList<Board>();
public static void main(String[] args) {
for (String queens : boards) { // create starter boards
boardObjects.add(new Board(queens));
}
int i;
ArrayList<Board> foundBoards = null;
for (i = 8; i > 0; i--) {
ArrayList<Board> newBoards = new ArrayList<Board>();
foundBoards = new ArrayList<Board>();
for (Board b : boardObjects) {
if (b.checkForImpact()) { // if any queen intercepts we get
// children
ArrayList<Board> boardsToBeAdded = b.getChildBoards(); // pass
// all
// permutations
// of
// queens
// once
// removed
for (Board bo : boardsToBeAdded) {
newBoards.add(bo); // add it in to the next list
}
} else {
foundBoards.add(b); // if we have no impact, we have a
// solution
}
}
if (!foundBoards.isEmpty())
break;
boardObjects.clear();
boardObjects = newBoards;
}
System.out.println("The maximum number of super-queens is: " + i);
ArrayList<String> winningCombinations = new ArrayList<String>();
for (Board board : foundBoards) {
String createdBoard = board.drawBoard();
boolean found = false;
for (String storedBoard : winningCombinations) {
if (storedBoard.equals(createdBoard))
found = true;
}
if (!found)
winningCombinations.add(createdBoard);
}
for (String board : winningCombinations) {
System.out.println(board);
}
}
}
The end output is:
The maximum number of super-queens is: 6
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|Q|_|
6|_|_|_|Q|_|_|_|_|
5|_|_|_|_|_|_|_|_|
4|_|_|_|_|_|_|_|Q|
3|_|Q|_|_|_|_|_|_|
2|_|_|_|_|Q|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|Q|_|_|_|_|_|_|_|
7|_|_|_|_|_|_|_|_|
6|_|_|_|_|Q|_|_|_|
5|_|_|_|_|_|_|_|Q|
4|_|Q|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|_|_|_|Q|_|_|
1|_|_|Q|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|_|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|Q|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|Q|_|_|_|_|
4|_|_|_|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|Q|_|_|_|_|_|
1|_|_|_|_|_|_|_|_|
A B C D E F G H
8|_|_|_|_|Q|_|_|_|
7|Q|_|_|_|_|_|_|_|
6|_|_|_|_|_|_|_|Q|
5|_|_|_|_|_|_|_|_|
4|_|_|Q|_|_|_|_|_|
3|_|_|_|_|_|_|Q|_|
2|_|_|_|_|_|_|_|_|
1|_|_|_|Q|_|_|_|_|
I've removed the duplicates and made a nice board printing method. don't remember the exact math, but this highlights 40 possible locations. There are others, just by looking, but we've found a fair chunk of them already! From here, we can gently shift individual queens around. From a cursory look, each board has a single piece that can be moved to 3 additional spaces, so now we know there are probably about 160 solutions.
Conclusions
With this application, the run-time on my machine was less than a second, meaning that if we attached this to a standard queens application, the additional knight's brute-forcing would have no impact on that process and have almost the same run-time. In addition, because only 6-piece puzzles are possible, we know that your eventual application run will finish its finding at the 6th piece being placed, as no more solutions are possible, since there are no viable 7-piece and 8-piece solutions.
In other words, finding the maximum super-queen layout is likely actually shorter than the maximum queen layout due to the additional restrictions!
Trying to brute-force such a question is a good way to get a feel for it. So I won't suggest looking up pre-cooked solutions at first.
One little remark though: I don't see the reason for the condition if (i != 0 || j != 0) { that you have there. You are working on Java arrays. Instead of 1 through 8, they go 0 through 7, but the 0 is the first column, you should not eliminate it, otherwise it's only a 7x7 board.
First, let me address your technical question: how to calculate the knight positions.
Take a sheet of quad paper, put a queen somewhere not less than two squares away from the edge. Then mark the end positions of a knight-move from it.
You'll end up with just 8 squares that need to be considered. There is no point in doing a 3x3 loop to find them. A better idea would be to prepare a static array with the relative coordinates of the knight moves - an array of 8 pairs of numbers - and loop on that. So you have only an 8-step loop. In each step of the loop, check for bounds (0 ≤ X + Xoffset < 8, 0 ≤ Y + Yoffset < 8 ), and you have the knight coordinates.
Second, there is no point checking the part of the board that's ahead of you. Since you have not covered the next row and those below it, there is no point in looking for queens there. The implications of this:
You'll never put another queen in the same row where you have just marked a queen position (because you threaten it horizontally). This means that if you mark a queen, you should use continue to break out of the inner loop to the next row.
You don't need checkrow(). When you start a row, there is no queen ahead of you. And if you followed the above bullet point, there is no queen on your back, either.
When you use checkcolumn, you start at row 0, but you can finish at the row before the one you are on (i-1). There are still no queens in the rows below you! The same is true for the diagonal checks.
Earlier I said that you need to prepare and check 8 knight positions. But now you know there is no queen at the knight positions ahead of you. So you only need to prepare an array with four knight positions - the ones above your position.
But most importantly... once you have finished and you have your queens in positions and print the board: you have a single solved board. You have proved that this number of queens is possible. But is it the highest number possible? You have not checked what happens if you don't put a queen on the first square of the first row, but on the second. Perhaps this will allow you to put in an extra queen later. And what about the queen in the second row? Maybe if you moved that, you would be able to put a queen somewhere below where you couldn't before?
So, now you have to actually do the same thing over again, changing one decision every time and working from there. In effect, you have many potential boards. Why? Because there may be more than one valid position on each row where you put that row's queen. So you have decided to put it in the first valid position. But what if you decide to put it in the second valid position? Or leave that row empty? Each such decision is followed by another set of decisions on the next row.
The different boards created by different decisions form a decision tree. The problem for you to consider, therefore, is how to work such a tree out. How to write your decision trail and then backtrack, change, fill another board and count the queens at each level. People here suggested recursion, because it lends itself nicely to such problems. Or you can keep a stack of decisions if you want. You can eliminate some of the potential boards based on symmetries.
I suggest you first make sure you understand your single board well, and then consider how to represent your decision tree and how to traverse it.
There are several questions here.
The first is: how many knight-queens can be placed on an nxn chessboard? Since a k-piece solution can trivially be reduced to a k-1 piece solution, it makes sense to start from the upper bound. That is, look for an n-piece solution, if that fails look for an n-1 piece solution, and so forth.
The second question is: how should I look for a k-piece solution? There are two classic strategies: depth-first and breadth-first. In the former, you consider one vertex of the search tree at a time and use backtracking on failure. In the latter, you consider one complete level of the search tree at a time.
Something that can make a great deal of difference to your search is to account for symmetry (in this case, rotations and reflections).
The third (implicit) question is: what is a good representation here? If your chess-boards are less than 8x8 in size then a 64-bit bit-pattern will do very nicely!
In practical terms, try to separate the three levels of your problem as far as you can. If you don't, you'll find that a choice in one level will severely limit your options at another level.
I am trying to find number of paths between top left and bottom right cells on a checker board. i can only move to the adjacent right and adjacent bottom cell. This way i can have a maximum of 2 non intersecting simple paths. I am using a recursive approach.
private void processMatrix()
{
if(matrix[0][0]!=1 || matrix[0][0]!=matrix[ROWS-1][COLUMNS-1])
System.out.println("No Path Exists between bottom right and top left cells");
int row=0;
int col=0;
traverse(row,col);
}
private boolean traverse(int row, int col)
{
path.add(new Point(row,col));
if(row+1<ROWS)
{
if(matrix[row+1][col]==0)
{
return false;
}
if(matrix[row+1][col]==1)
{
traverse(row+1,col);
}
}
if(col+1<COLUMNS)
{
if(matrix[row][col+1]==0)
{
return false;
}
if(matrix[row][col+1]==1)
{
traverse(row,col+1);
}
}
if(col==COLUMNS-1 && row==ROWS-1)
return true;
return false;
}
But with this code i am only able to traverse the lower triangular matrix. And when i reverse the order of if blocks in the traverse() function i am only able to traverse a path in the upper triangular matrix. Unable to figure out what is wrong. I also want to detect intersecting paths. Please help.
EDIT:
The matrix consists of 0s and 1s.
A path exists if it is connected by adjacent cells containing only 1s. In other words the path will be a chain of 1s.
You seem to be overcomplicating things with your code. If your matrix is 0s and 1s, use boolean instead of int. Non-intersecting paths seems a bit silly, since all paths are equally valid in taxicab geometry. Here's the simple solution for finding the number all paths, it will show you how it works with the block of system.out prints:
int rows = 9;
int columns = 8;
boolean[][] matrix = new boolean[rows][columns];
for (boolean[] arr : matrix) {/* Set values of matrix such that true = can pass thru that space, false = space blocked */
Arrays.fill(arr, true);
}
matrix[4][6] = false;
matrix[2][5] = false;
int[][] paths = new int[rows][columns];//number of paths reaching each space in i steps
paths[0][0] = 1; //Starting space
for (int i = 0; i < rows + columns - 2; i++) {//Taxicab distance is always x+y, i = distance travelled so far
int[][] newPaths = new int[rows][columns]; //number of paths reaching each space in i+1 steps
for (int x = i >= columns ? i - columns + 1 : 0; x <= i && x < rows;) { //x is traditionally columns but it doesn't matter
int y = i - x; //if statement is x declaration ensures that this is < columns
int newX = x + 1; //will be used repeatedly
int newY = y + 1; //will be used repeatedly
if (newX < rows && matrix[newX][y]) newPaths[newX][y] += paths[x][y];
if (newY < columns && matrix[x][newY]) newPaths[x][newY] += paths[x][y];
x = newX;
}
paths = newPaths;
for (int x = 0; x < rows; x++) { //optional, show the algorithm at work
for (int y = 0; y < columns; y++) {
int r = paths[x][y];
System.out.print(r);
if (r < 100) System.out.print(" ");
if (r < 10) System.out.print(" ");
}
System.out.println();
}
System.out.println();
}
System.out.println(paths[rows - 1][columns - 1]); //result
If all you want to determine is whether a path exists, replace int[][] paths with boolean[][] paths and change the operations accordingly.
This is a fundamental dynamic programming problem.
Let dp[R][C] be the number of paths from the top-left cell to the cell on row R and column C (1-indexed).
Initial values (when R or C is 1):
dp[R][1] = 1 if matrix[i][1] has value 1 for i = 1..R, otherwise dp[R][1] = 0.
dp[1][C] = 1 if matrix[1][j] has value 1 for j = 1..C, otherwise dp[1][C] = 0.
Then dp[R][C] = dp[R-1][C] + dp[R][C-1] if matrix[R][C] = 1, otherwise dp[R][C] = 0 (for R, C >= 2)
And this is it. The intuition behind this idea is that if we know that we can get to cell on row R-1, column C by N different roads, then if we go down once, we will get N different roads to cell [R, C]. Analogically for going right from cell [R, C-1] to [R, C].
Finally, the answer is in dp[N][M], where N and M are the dimensions of the matrix.
I decided to write a logic solving algorithm for my Sudoku application. What I wrote works for a limited amount of grid values, but then the recursion stops way too soon.
What my methods do:
addToThirdDimension(): A three dimensional array stores any possible values that can be put into the grid value at logicGrid[x][y]. This method refreshes the three dimensional array. It does this by testing values 1-9 in every grid index, and if it's valid, it adds that number to the array. If not, it sets that value to zero.
checkValues(): Checks how many possibilities are left in the three dimensional grid. It goes through the logicGrid and returns the number of non-zero values are in the grid.
checkSingleValue(int row, int col): Checks logicGrid[row][col] to see if there is one and only one value left in there (If there is one value left, it is the only possibility for the grid element at [row, col]). It returns the amount of non-zero values that are in that grid location.
getSingleValue(int row, int col): Returns the single number that's left in logicGrid[row][col]
immutableValues: A two dimensional boolean array that stores whether or not a specific grid element is immutable or not. If it is immutable, the solve method should not touch it.
public boolean solveWithLogic(){
addToThirdDimension();
if(checkValues() == 0){
return true;
}
for(int row = 0; row < 9; row++){
for(int col = 0; col < 9; col++){
if(!immutableValues[row][col]){
if(checkSingleValue(row, col) == 1){
sGrid[row][col] = getSingleValue(row, col);
setValues[row][col] = true;
addToThirdDimension();
}
}
}
}
if(checkValues() != 0){
solveWithLogic();
} else{
return true;
}
return false;
}
I cannot see where I am going wrong. After a certain number of tries, checkValues returns 0 even though there should be more possibilities. Here is the code for addToThirdDimension() as I am sure that if something is wrong, it is here.
sGrid is the main two-dimensional integer array that stores the values for the puzzle.
public void addToThirdDimension(){
logicGrid = new int[9][9][9];
for(int x = 0; x < 9; x++){
for(int y = 0; y < 9; y++){
for(int z = 0; z < 9; z++){
logicGrid[x][y][z] = z + 1;
}
}
}
int[][] temp1 = sGrid;
for(int row = 0; row < 9; row++){
for(int col = 0; col < 9; col++){
if(setValues[row][col]){
for(int i = 0; i < 9; i++){
logicGrid[row][col][i] = 0;
}
} else{
for(int i = 1; i <= 9; i++){
temp1[row][col] = i;
if(!isColumnValid(col, temp1) && !isRowValid(row, temp1) &&
!isQuadrantValid(row, col, temp1){
logicGrid[row][col][i-1] = 0;
}
}
}
temp1[row][col] = sGrid[row][col];
}
}
}
The code isn't too efficient at the moment. I want to get it working before I start minimizing solve times.
The first thing I would do is create a SudukoCell object that stores your possible values in it. Then create a SudukoBoard with a 2d array of SudukoCells. Also give it an array of SudukoAreas. One area for rows, one area for cols, and one area for blocks.
Add your suduko cells appropriately.
This will help you consolidate your legwork and prevent silly mistakes.
then every time you solve a number, you can go to the cells in each of its areas and remove the number you solved from them.