I'm working on a Java program that checks if a sudoku puzzle is solved or not. I have finished the horizontal and vertical number check part. But when trying to check squares, I can't do anything. Here is how my check system works.
This is what I want to make. Hope someone helps because I'm on a hard situation with square check.
int[][] SudokuBoard = new int[9][9];
// I didn't wrote the sudoku board completely hope you understood how sudoku table looks like.
public static boolean checkSquares(int[][] SquareBoard) {
int retr = false;
int loop = 0;
int[] extraboard = new int[9];
int[] truelist ={1,2,3,4,5,6,7,8,9};
for(int i = 1; i <=9 ; I++) {
//here , extraboard will have the numbers in " i " numbered sudoku square.( i is like first //,second)
Arrays.sort(extraboard);
for(int j = 0; j < 9; j++) {
if(extraboard[j] == truelist[j])
loop += 1;
}
extraboard = new int[9];
}
if(loop == 81)
retr == true;
return retr;
}
You could do
int count = 0;
for(int k = 0; k < 9; k++) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
extraboard[count++] = SquareBoard[i+3*k/3][j+k%3*3];
}
}
Arrays.sort(extraboard);
for(int j = 0; j < 9; j++) {
if(extraboard[j] == truelist[j])
loop += 1;
}
extraboard = new int[9];
count = 0;
}
The actual formula to calculate the location in the box is quite simple. As the board is split into rows and column, getting the location of the row and column needs to get offset based on the location of the box in the full area.
i here counts the index within the box of the row. As each row of boxes has a length of 3 in a 9x9 sudoku we need to increase the row number by 3 each time we get 3 boxes in. To figure out and only add 3 we can use some integer division.
For example:
i+i.length*k/i.length
This is obviously an syntax error as i doesn't have length but can consider it as the limit of i in the loop (in this case 3).
This would then get the current row in the box (the first i) and add that to the offset of boxes in the sudoki. That is for every 3 boxes k/i.length becomes 1 more, and we then multiply that with 3 to get the offset of 3.
In the column part we have a bit of an bigger issue as we need to offset it for every 3 we move left in the array and reset it when we get back to boxes on the far left.
So the forumla would become
j + (k%i.length)*j.length
This would give us the column in the box we are in, then we offset by the box location with k%i.length. The reason we use the i.length and not the j.length is that we need to calculate the offset by rows and then offset it by the length of the box column wise.
With this you can then apply to this to any size board. 2x2, 2x3, 3x2, 3x3 or bigger even.
public static boolean checkSquares(int[][] SquareBoard) {
int i=0, extraboard=0;
for (;i<9;i++,extraboard=0) {
for (int j=0;j<9;j++)
extraboard+=1<<(SquareBoard[i/3*3+j/3][i%3*3+j%3]-1);
if (extraboard!=(1<<9)-1) // 511, binary(511) = 111111111
break;
}
return i==9;
}
This is a solution i came up with. it uses 4 nested loops but the time complexity is still O(n^2). Basically i check the first 3 boxes on top, then the 3 boxes in the middle, then the last 3 boxes.
for (int l = 0; l < 9; l+= 3){
for (int i = 0; i < 9; i += 3){
HashSet<Character> set = new HashSet<>();
for (int j = l; j < l+3; j++){
for (int k = i; k < i+3; k++){
if (!set.contains(board[j][k])){
if (board[j][k] != '.')
set.add(board[j][k]);
}
else
return false;
}
}
}
}
return true;
and note that the sudoku might not be complete, and the missing numbers are replaced by ' . '
Related
I'm trying to print an element of a 2D array by designating it's location with an index. Say, I want to print location 3 which would be String[1][0] for my array.
String[][] fruit = new String[2][2];
fruit[0][0] = "apple"; //position 1
fruit[0][1] = "banana"; //position 2
fruit[1][0] = "pear"; //position 3
fruit[1][1] = "melon"; //position 4
I would like to call fruit[1][0] position 3 so when I ask to print "position 3" it gives me "pear".
What you're looking for is obviously the literal position of a cell since arrays start from an index value of 0. You also need to keep in mind that a 2D Array can possibly have different number of columns for any given row. The first and second rows for example may have 4 columns, the fifth row might have 6 columns, and the sixth, seventh row may have 4 columns again. Unless you know for sure that all columns within the Array are indeed fixed to a specific length (a "square" 2D Array), I can't see an advantage to this scheme.
Never the less, this can be easily done with two for loops (one nested within the other), for example:
String[][] array = {
{"cell 1", "cell 2"}, // Row 1 (index 0)
{"cell 3", "cell 4", "cell 5"}, // Row 2 (index 1)
{"cell 6", "cell 7"}}; // Row 3 (index 2)
int yourDesiredCell = 5;
int cellCount = 0;
boolean found = false;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
cellCount++;
if (cellCount == yourDesiredCell) {
System.out.println(array[i][j]);
found = true;
break;
//return array[i][j];
}
}
if (found) {
break;
}
}
You could also place this into a class method, for example:
public static String getCellData(String[][] array, int yourDesiredCell) {
int cellCount = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
cellCount++;
if (cellCount == yourDesiredCell) {
return array[i][j];
}
}
}
return null;
}
Another method that could be handy is retrieving the total number of actual cells contained within the 2D Array (if you don't already know):
public static int getTotalCellCount(String[][] array) {
int cellCount = 0;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
cellCount++;
}
}
return cellCount;
}
What I got from your question was that there is a multi-dimensional array A of size say nxm where n is number of rows and'mis number of columns. You want to get let say 1st element which will beA[0][0], but you don't know how to convert 1` into indices for the array.
Lets do this for a 2d array A of size nxm, then you can extend it to 3d etc too. Remember that each A[i] is an array of'melements, hence the position of row where the element isx/m, i=x/m. No need to make it 0-indexed because the integer division of java does that for you. If i>=n`, then we should say element is not present.
Now you have to decide the position of the element in m elements. Hence j or position of the column is x%m. This will give you index b/w 0 and m-1 which is correct range of j, but for an element in the first place it should give 0, but it's giving 1. Hence it js not 0-indexed. So j= x%m -1 but for (m-1)th element its giving
-1 as x would be divisible by m or x%m=0. So use ternary operator here, j = x%m-1 < 0 ? m-1 : x%m-1.
i = x/m ;
if(i<n){
j = x%m -1 < 0 ? m-1 : x%m -1 ;
}else{
System.out.println("Element " +m+" does not exist") ;
}
I would like to suggest another approach with a time complexity O(n).
public String getByPosition(int pos,String[][] mulArr){
int row,col;
int temp = pos;
while(temp % mulArr.length != 0)temp++;
row = (temp / mulArr.length) - 1;
col = ((pos % mulArr[0].length) - 1 < 0) ? mulArr[0].length - 1 : (pos % mulArr[0].length) - 1;
return mulArr[row][col];
}
public static int[][] solve(int[][] input){
for (int i = 0; i < 9*9; i++){
if(input[i / 9][i % 9] != 0){
continue;
}
for (int j = 1; j <= 9; j++){
if(validNumber(input, i / 9, i % 9, j)){
input[i / 9][i % 9] = j;
solve(input);
}
}
}
return input;
}
This method should solve a (solvable) sudoku puzzle via backtracking regardless of the initial situation. It works like this:
Given a sudoku puzzle it iterates from the upper left corner over each row to the lower right corner of the 2D array. When there is already a number, it gets skipped. When there is a zero (empty field) it calculates possible values via the validNumber method. The first valid number (from 1 to 9) is put in the field and the method goes to the next field.
In this algorithm the method does not now whether or not a valid number will eventually render the puzzle unsolvable.
I want to alter it like this:
At the end, when the method finishes iterating through the whole 2d array, every entry of the array gets tested if it is a zero or not.
If there is even one zero the whole algorithm must go to the place where the very first "valid" number was put in. Now, the next "valid" number is put in and so on until there are no zeroes at the end of the algorithm.
I have some troubles implementing this thought. It seems to me there must be an other for loop somewhere, or something like a goto statement, but I don't know where to put it.
Any advice?
I implemented a Sudoku solver once before. It was a bit more complicated than what you had, but solved the game in a blink. :)
What you are attempting to do is solve Sudoku by "Brute Force" and using (tail) recursion. That means you are attempting to solve the board by iterating over all 981 possible combinations. 9 to the power of 81 is... well it's a big number. And so your approach will take eternity, but you'll run out of stack space from the tail recursion much sooner.
When I implemented Sudoko, it was more straight up. It kept a 9x9 array of "items", where each item was the value in the square, and an array of 9 booleans representing candidates (true == viable, false == eliminated). And then it just did a non-recursive loop of solving the board.
The main loop would start with the simple process of finding squares with only 1 remaining candidate. Then the next step would do simple candidate elimination based on values already assigned. Then it would work its way into more complicated elimination techniques such as X-Wing.
Your algorithm does not actually backtrack. It moves forward if it can, but it never moves backwards when it realizes it's stuck in a corner. This is because it never returns any knowledge up the stack, and it never resets squares. Unless you get really lucky, your code will get the game board into a cornered state, and then print out that cornered state. To backtrack, you need to reset the last square you set (the one that got you cornered) to zero, so your algorithm will know to keep trying other things.
For understanding backtracking, I highly recommend a book called The Algorithm Design Manual by Steven Skiena. I read it when I was preparing for SWE interviews, and it really improved my knowledge of backtracking, complexity, and graph search. The second half of the book is a catalog of 75 classic algorithmic problems, and Sudoku is one of them! He has an interesting analysis of optimizations you can make to prune the search tree and solve very hard puzzle boards. Below is some code I wrote a long time ago after reading this chapter (probably not that high quality by my current standards, but it works). I just read through it really quickly and added the solveSmart boolean in the solve method which allows you to turn one of those optimizations on or off, which results in a pretty big time savings when solving a "hard" class Sudoku board (one with only 17 squares filled in to start with).
public class Sudoku {
static class RowCol {
int row;
int col;
RowCol(int r, int c) {
row = r;
col = c;
}
}
static int numSquaresFilled;
static int[][] board = new int[9][9];
static void printBoard() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(" " + (board[i][j] == 0 ? " " : board[i][j]) + " ");
if (j % 3 == 2 && j < 8)
System.out.print("|");
}
System.out.println();
if (i % 3 == 2 && i < 8)
System.out.println("---------|---------|---------");
}
System.out.println();
}
static boolean isEntireBoardValid() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (!isBoardValid(i, j)) {
return false;
}
}
}
return true;
}
static boolean isRowValid(int row) {
int[] count = new int[9];
for (int col = 0; col < 9; col++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isColValid(int col) {
int[] count = new int[9];
for (int row = 0; row < 9; row++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isSquareValid(int row, int col) {
int r = (row / 3) * 3;
int c = (col / 3) * 3;
int[] count = new int[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int n = board[r + i][c + j] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
}
return true;
}
static boolean isBoardValid(int row, int col) {
return (isRowValid(row) && isColValid(col) && isSquareValid(row, col));
}
static RowCol getOpenSpaceFirstFound() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
return new RowCol(i, j);
}
}
}
return new RowCol(0, 0);
}
static RowCol getOpenSpaceMostConstrained() {
int r = 0, c = 0, max = 0;
int[] rowCounts = new int[9];
int[] colCounts = new int[9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] != 0)
rowCounts[i]++;
if (board[j][i] != 0)
colCounts[i]++;
}
}
int[][] squareCounts = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int count = 0;
for (int m = 0; m < 3; m++) {
for (int n = 0; n < 3; n++) {
if (board[(i * 3) + m][(j * 3) + n] != 0)
count++;
}
}
squareCounts[i][j] = count;
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
if (rowCounts[i] > max) {
max = rowCounts[i];
r = i;
c = j;
}
if (colCounts[j] > max) {
max = rowCounts[j];
r = i;
c = j;
}
}
}
}
return new RowCol(r, c);
}
static boolean solve() {
if (81 == numSquaresFilled) {
return true;
}
boolean solveSmart = true;
RowCol rc = solveSmart ? getOpenSpaceMostConstrained() : getOpenSpaceFirstFound();
int r = rc.row;
int c = rc.col;
for (int i = 1; i <= 9; i++) {
numSquaresFilled++;
board[r][c] = i;
if (isBoardValid(r, c)) {
if (solve()) {
return true;
}
}
board[r][c] = 0;
numSquaresFilled--;
}
return false;
}
public static void main(String[] args) {
// initialize board to a HARD puzzle
board[0][7] = 1;
board[0][8] = 2;
board[1][4] = 3;
board[1][5] = 5;
board[2][3] = 6;
board[2][7] = 7;
board[3][0] = 7;
board[3][6] = 3;
board[4][3] = 4;
board[4][6] = 8;
board[5][0] = 1;
board[6][3] = 1;
board[6][4] = 2;
board[7][1] = 8;
board[7][7] = 4;
board[8][1] = 5;
board[8][6] = 6;
numSquaresFilled = 17;
printBoard();
long start = System.currentTimeMillis();
solve();
long end = System.currentTimeMillis();
System.out.println("Solving took " + (end - start) + "ms.\n");
printBoard();
}
}
Eventually validNumber() method will not return any number because there is no possibilities left that means one of the previous choices was incorrect. Just imagine that the algorithm is started with the empty grid (obviously this puzzle is solvable1).
The solution is to keep tree of possible choices and if some choices are incorrect, then just remove them from the tree and use the next available choice (or step back on a higher level of the tree, if there is no choice left in this branch). This method should find a solution if any. (Actually this is how I implemented my sudoku solver some time ago.)
1 IMHO there are 3 different kinds of sudoku:
"true" correct sudoku that has a single unique complete solution;
ambiguous sudoku that has multiple distinct complete solutions, e.g. a puzzle with only 7 different numbers, so it has at least two distinct solutions that differ by swapping 8th and 9th numbers;
incorrect sudoku that has no complete solution, e.g. with a row with two or more occurrences of the same number.
With this definition, a solver algorithm should either:
prove that there is no solution;
return complete solution that satisfies the initial grid.
In the case of a "true" sudoku the result is a "true" solution by definition. In the case of an ambiguous sudoku the result can be different depending on the algorithm. An empty grid is the ultimate example of ambiguous sudoku.
I am doing an N Queens Program in Java. I was able to print all the solutions where each Queen is on a different row and column. Now I need to keep track of the diagonals for collisions. So there are 2n-1 diagonal lines on a 2D array. The algorithm wants us to there are 2n-1 negative diagonal lines and 2n - 1 positive diagonal lines on the chessboard. There is an array of size 2n-1, called d1, that keeps track of the number of queens, i.e., the number of collisions, on each of the 2n-1 negative diagonal lines. If there are k queens on the mth negative diagonal line, there are k-1 collisions on this diagonal line. The
number k is written into the mth element of the d1 array. Similarly, we choose another array with size 2n-1, called d2, for 2n-1 positive diagonal lines.
Here is my method for D2, but I am completely lost. I know that all the up diagonals are row + col, but that is it.
public void D2(){
int[] upDiag = new int[2*board.length - 1];
int numberOfCollisions = 0;
for(int row = 0; row < board.length; row++){
for(int col = 0; col < board.length; col++){
if(isQueen(row, col)){
upDiag[numberOfCollisions++];
}
}
}
}
I've written a three-part series on the Eight-Queens/N-Queens Problem.
Here's a general outline of the problem, and a recursive solution.
Here's a genetic algorithm solution.
Here's a simulated annealing solution.
For the collision checking itself, something like this works very well:
double assessFitness(Integer[] candidate) {
int collisions = 0;
final int MAXIMUM_COLLISIONS = calculateMaxCollisions();
for (int i = 0; i < GRID_SIZE - 1; i++) {
for (int j = i + 1; j < GRID_SIZE; j++) {
if ((candidate[i].equals(candidate[j])) || j - i == Math.abs(candidate[i] - candidate[j]))
collisions++;
}
}
return (MAXIMUM_COLLISIONS - collisions) / (double) MAXIMUM_COLLISIONS;
}
Note that this is adapted from my genetic algorithm solution. I do explain why I return a value that scales from 0 to 1 in the blog article, but in your case a slight modification would yield the result you're looking for:
int countCollisions(Integer[] candidate) {
int collisions = 0;
final int MAXIMUM_COLLISIONS = calculateMaxCollisions();
for (int i = 0; i < GRID_SIZE - 1; i++) {
for (int j = i + 1; j < GRID_SIZE; j++) {
if ((candidate[i].equals(candidate[j])) || j - i == Math.abs(candidate[i] - candidate[j]))
collisions++;
}
}
return collisions;
}
In order for this to work, you do need to calculate the maximum allowable number of collisions for your N-Queens problem.
private int calculateMaxCollisions() {
int sum = 0;
for (int i = GRID_SIZE - 1; i > 0; i--) {
sum += i;
}
return sum;
}
I am having trouble creating multiple arrays with a loop in Java. What I am trying to do is create a set of arrays, so that each following array has 3 more numbers in it, and all numbers are consecutive. Just to clarify, what I need to get is a set of, let's say 30 arrays, so that it looks like this:
[1,2,3]
[4,5,6,7,8,9]
[10,11,12,13,14,15,16,17,18]
[19,20,21,22,23,24,25,26,27,28,29,30]
....
And so on. Any help much appreciated!
Do you need something like this?
int size = 3;
int values = 1;
for (int i = 0; i < size; i = i + 3) {
int[] arr = new int[size];
for (int j = 0; j < size; j++) {
arr[j] = values;
values++;
}
size += 3;
int count = 0;
for (int j : arr) { // for display
++count;
System.out.print(j);
if (count != arr.length) {
System.out.print(" , ");
}
}
System.out.println();
if (i > 6) { // to put an end to endless creation of arrays
break;
}
}
To do this, you need to keep track of three things: (1) how many arrays you've already created (so you can stop at 30); (2) what length of array you're on (so you can create the next array with the right length); and (3) what integer-value you're up to (so you can populate the next array with the right values).
Here's one way:
private Set<int[]> createArrays() {
final Set<int[]> arrays = new HashSet<int[]>();
int arrayLength = 3;
int value = 1;
for (int arrayNum = 0; arrayNum < 30; ++arrayNum) {
final int[] array = new int[arrayLength];
for (int j = 0; j < array.length; ++j) {
array[j] = value;
++value;
}
arrays.add(array);
arrayLength += 3;
}
return arrays;
}
I don't think that you can "create" arrays in java, but you can create an array of arrays, so the output will look something like this:
[[1,2,3],[4,5,6,7,8,9],[10,11,12,13...]...]
you can do this very succinctly by using two for-loops
Quick Answer
==================
int arrays[][] = new int[30][];
for (int j = 0; j < 30; j++){
for (int i = 0; i < (j++)*3; i++){
arrays[j][i] = (i++)+j*3;
}
}
the first for-loop tells us, via the variable j, which array we are currently adding items to. The second for-loop tells us which item we are adding, and adds the correct item to that position.
All you have to remember is that j++ means j + 1.
Now, the super long-winded explanation:
I've used some simple (well, I say simple, but...) maths to generate the correct item each time:
[1,2,3]
here, j is 0, and we see that the first item is one. At the first item, i is also equal to 0, so we can say that, here, each item is equal to i + 1, or i++.
However, in the next array,
[4,5,6,7,8,9]
each item is not equal to i++, because i has been reset to 0. However, j=1, so we can use this to our advantage to generate the correct elements this time: each item is equal to (i++)+j*3.
Does this rule hold up?
Well, we can look at the next one, where j is 2:
[10,11,12,13,14...]
i = 0, j = 2 and 10 = (0+1)+2*3, so it still follows our rule.
That's how I was able to generate each element correctly.
tl;dr
int arrays[][] = new int[30][];
for (int j = 0; j < 30; j++){
for (int i = 0; i < (j++)*3; i++){
arrays[j][i] = (i++)+j*3;
}
}
It works.
You have to use a double for loop. First loop will iterate for your arrays, second for their contents.
Sor the first for has to iterate from 0 to 30. The second one is a little less easy to write. You have to remember where you last stop and how many items you had in the last one. At the end, it will look like that:
int base = 1;
int size = 3;
int arrays[][] = new int[30][];
for(int i = 0; i < 30; i++) {
arrays[i] = new int[size];
for(int j = 0; j < size; j++) {
arrays[i][j] = base;
base++;
}
size += 3;
}
I'm a complete newbie when it comes to Java and I've been working on a simple program which creates a grid with multiple slots. Each slot has an X and a Y value and is stored in an ArrayList called "s".
Here's my code:
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
s.add(new Slot(j, i));
}
}
Height and width are user inputed values.
It's a simple loop within a loop and essentially it should work but instead of creating multiple slots with the values 0, 0, 1,0 2, 0 3, 0 and so forth until it should increase the Y axis by one it never increases the Y-value. Instead after doing the first loop it will go back to 0, 0 instead of 0, 1.
Also here's the how it's supposed to print the values:
for (int i = 0; i <= height; i++) {
for (int j = 0; j <= width; j++) {
System.out.print(s.get(j));
}
System.out.println("");
}
Example:
0,0
1,0
2,0
3,0
...
9,0
0,0 (instead of 0,1)
My question is why on earth doesn't my first loop ever increase the value of i? Sorry if I sound like an idiot, I'm a total noob.
You have a problem in your printing function.
I don't know what s is but:
for (int i = 0; i <= height; i++) {
for (int j = 0; j <= width; j++) {
System.out.print(s.get(j));
}
System.out.println("");
}
Get objects based on j value only. You need to get objects based on i and j in order to get all values.
Or you can just iterate over all objects in s (if s is a Collection):
for (Slot sl : s) {
System.out.println(sl);
}
The j value only ranges between 0 and width - 1 so s.get(j) is only going to access the first width items in s. Try this instead:
for (int i = 0; i <= height; i++) {
for (int j = 0; j <= width; j++) {
System.out.print(s.get(i * width + j));
}
System.out.println("");
}
Or you could just iterate over the contents of s and not use nested for loops for the retrieval.
You don't need the nested loop when printing, Just iterate over the ArrayList:
for(Slot slot : s )
{
System.out.println(slot);
}
Your problem is the print function. Just iterate over s and print each slot:
for (Slot slot : s) {
System.out.println(slot);
}
As it is implemented now, you print items in s from indexes 0 -> width over and over again, height times.
Also, learn about the for-each loop, available from Java 5 instead of using get(index):
Oracle Tutorial
The problem is you are storing height * width elements in a one dimensional array - ArrayList but retreiving only width number of elements.
Instead of arraylist of Slot for s, use two dimensional array.
Slot[][] s = new Slot[width][height];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
s[j][i](new Slot(j, i));
}
}
for (int i = 0; i <= height; i++) {
for (int j = 0; j <= width; j++) {
System.out.print(s[j][i]);
}
System.out.println("");
}
you only print j from the same place every time