Hi I am trying to create a matrix on the console using 2D array. The idea is that the output should look like this one :
1|8|9 |16
2|7|10|15
3|6|11|14
4|5|12|13
Is there any one who has an idea how it can be done?
Few things you can guess from the matrix: -
First, you have to traverse all rows of a columns first before moving to the next column
Second, you need to alternate between downwards and upwards direction on each iteration
So, you would need two nested for loop, for iterating through rows for a particular column. One will go from row 0 to max - 1, and the next will go from row = max - 1 to 0.
Now, to alternate the iteration direction, you can use a boolean variable, and toggle it after each iteration of inner loop finishes.
Each loop needs to be enclosed inside an if-else. Both of them will be executed on a certain condition. If boolean downwards = false;, then loop moving upwards will be executed and vice-versa.
On each iteration, fill the current cell with an integer counter, that you would have to initialize with 1, and increment it after each fill.
Pseudo code : -
// Initialize variables row, col, and count = 1
boolean goDown = true;
int[][] matrix = new int[row][col]; // declare matrix
for i = 0 to col:
if (goDown)
for j = 0 to row: // Move in downwards direction
assign count++ to matrix[j][i]
// assign to `[j][i]` because, we have to assign to rows first
goDown = false; // Toggle goDown
else
for j = row - 1 to 0: // Move in upwards direction
assign count++ to matrix[j][i]
goDown = true; // toggle goDown
}
Just some psuedo-code, hope it helps and gives you something to start with.
boolean goUp = false;
boolean goDown = true;
size = 4;
matrix[size][size];
k = 0;
l =0;
loop i->0 i < size*size i++
matrix[l][k] = i;
if(l==size and goDown)
goDown = false;
goUp = true;
k++;
else if(l==0 and goUp)
goDown = true;
goUp = false;
k++;
else
l = l+ (1*goDown?1:-1);
end loop;
finally with your help and after looking carefully at how multidimensional arrays work I solved the problem which now is looking quite simple to me.
int a = 4;
int b = 4;
int c = 1;
boolean direction = true;
int[][] arrey = new int[a][b];
for (int y = 0; y <= b - 1; y++) {
if (direction) {
for (int x = 0; x <= a - 1; x++) {
arrey[x][y] = c;
c++;
}
direction = false;
} else {
for (int x = a - 1; x >= 0; x--) {
arrey[x][y] = c;
c++;
}
direction = true;
}
}
for (int x = 0; x <= a - 1; x++) {
for (int y = 0; y <= b - 1; y++) {
System.out.print("["+arrey[x][y]+"]");
}
System.out.println("");
}
const matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
];
let i = 1;
for (let col = 0; col < matrix[0].length; col++) {
if (col % 2 === 1) {
for (let row = matrix.length - 1; row >= 0; row--) {
matrix[row][col] = i++;
}
} else {
for (let row = 0; row < matrix.length; row++) {
matrix[row][col] = i++;
}
}
}
console.table(matrix);
Related
I am writing a small program of how to calculate sum of neighbours of a given position in a grid.
for some reason the program does not recognize the right value as correct. I was wondering if that may be because i am using try catch to restrict out of bounds or if it something else i have missed?
i am using a simple 3x3 grid numbered 1 - 9. i have used the same matrix for many other tests so assume there is nothing wrong with the grid. This even though i get 11 when debugging and checking step by step. i dont quite understand, does anyone have an idea?
the -1 in sum was simply to force it to 11 (2+4+5) but the program still yields false when running the input positions. either there is something ive missed or something i have not understood
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
out.println(sumNeighbours(matrix, 0, 0) == 11);
int sumNeighbours(int[][] matrix, int row, int col) {
int sum = -1;
try {
for (int i = row - 1; i <= row; i++) {
for (int j = col - 1; j <= col; j++) {
sum = sum + matrix[i][j];
}
}
} catch (ArrayIndexOutOfBoundsException e) {
} return sum;
Simple printouts (or better: using a debugger
) show you what is happening:
int sumNeighbours(int[][] matrix, int row, int col) {
int sum = 1;
try {
for (int i = row - 1; i <= row; i++) {
for (int j = col - 1; j <= col; j++) {
System.out.println("Step 1 invalid indecies: i " + i +" j "+j);
sum = sum + matrix[i][j];
}
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Step 2 exiting loop, muted exception");
}
System.out.println("Step 3 returning sum "+sum);
return sum;
}
Side note: exceptions are just that. They are meant to handle exceptional situations. Avoid using exceptions to control your program.
I'm going to post this here as a community wiki, so as not to detract from cOder's answer (1+ to it, by the way), but the key is to write your code to avoid running into AIOOBE, to create loop start and end values that prevent this from happening, something like:
int sumNeighbours(int[][] matrix, int row, int col) {
int sum = 0;
int iStart = Math.max(0, row - 1);
int iEnd = Math.min(matrix.length, row + 2);
for (int i = iStart; i < iEnd; i++) {
int jStart = Math.max(0, col -1);
int jEnd = Math.min(matrix[i].length, col + 2);
for (int j = jStart; j < jEnd; j++) {
sum += (i == row && j == col) ? 0 : matrix[i][j];
}
}
return sum;
}
In the first iteration i and j is equal to -1 and you are trying to get value from matrix[-1][-1] and then exception is thrown. Catch block is empty so no operation is done and finally your program returns sum (it is -1).
If you want to continue iteration after exception you should do something like this:
for (int i = row - 1; i <= row; i++) {
for (int j = col - 1; j <= col; j++) {
try {
sum = sum + matrix[i][j];
}
catch (Exception e) {
// do nothing
}
}
} return sum;
In this case only adding is in the loop, so error doesn't stop it.
PS: try to avoid handling situations like this with try catches
I wrote a program to try to solve the 8 queens problem and one part of it required me to test all of the forward and backward diagonals to make sure there were no conflicts. I got the backwards to work perfectly but this part of the forward one was returning true while I was testing and I really can't figure out why. And help would be greatly appreciated :)
class NonAttackingQueen {
static char [][] board = { {'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'},
{'X','Q','X','X','X','X','X','X'},
{'Q','X','X','X','X','X','X','X'},
{'X','X','X','X','X','X','X','X'} };
public static boolean diagonalsClear () {
int numQueens;
boolean clear = true;
for (int numSpots = 1; numSpots < 9; numSpots++) {
numQueens = 0;
for (int row = 0; row < numSpots - 1; row++) {
if (board[row][numSpots - 1 - row] == 'Q')
numQueens++;
}
if (numQueens > 1) {
clear = false;
break;
}
}
for (int numSpots = 7; numSpots > 0; numSpots--) {
numQueens = 0;
for (int row = 7; row > 7 - numSpots; row--) {
if (board[row][15-row-numSpots] == 'Q')
numQueens++;
}
if (numQueens > 1) {
clear = false;
break;
}
return clear;
}
}
Little trick to solve this problem. It is obvious, that you have mistake with matrix row and column indices calculation, and your loops do not cover all cells in it. Easiest way to check it, just print it out to console. I can see, that you have problem with for (int row = 0; row < numSpots - 1; row++). Firs iteration, when numSpots=1 it skips this loop. Correct is for (int row = 0; row <= numSpots - 1; row++).
Let me give you some notes about your example. I can see that two upper and lower part of the matrix you check with opposite direction, upper one you start with row=0 and lower one - col=0. I think to do the same calculation is much better for understanding. You could decomposite you task into three simple once:
Check one single diagonal, starting with given row and column;
check upper diagonals;
check lower diagonals.
I think example below is more clear for reading:
private static boolean isDiagonalClear(int row, int col) {
int total = 0;
do {
if (board[row--][col++] == 'Q')
total++;
} while (total <= 1 && row >= 0 && col < 8);
return total <= 1;
}
public static boolean diagonalsClear() {
for (int row = 0; row < 7; row++)
if (!isDiagonalClear(row, 0))
return false;
for (int col = 0; col < 8; col++)
if (!isDiagonalClear(7, col))
return false;
return true;
}
I am writing a sudoku board game generator. My code looks like this:
/**
* Created by szubansky on 3/9/16.
*/
public class SudokuBoard {
static int N = 9;
static int[][] grid = new int[N][N];
static void printGrid()
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++) {
System.out.printf("%5d", grid[row][col]);
}
System.out.println("\n");
}
}
private static boolean checkRow(int row, int num)
{
for( int col = 0; col < 9; col++ )
if(grid[row][col] == num)
return false;
return true;
}
private static boolean checkCol(int col, int num)
{
for( int row = 0; row < 9; row++ )
if(grid[row][col] == num)
return false;
return true;
}
private static boolean checkBox(int row, int col, int num)
{
row = (row / 3) * 3;
col = (col / 3) * 3;
for(int r = 0; r < 3; r++)
for(int c = 0; c < 3; c++)
if(grid[row+r][col+c] == num)
return false;
return true;
}
public static boolean fillBoard(int row, int col, int[][] grid)
{
if(row==9) {
row = 0;
if (++col == 9)
return true;
}
if(grid[row][col] != 0)
return fillBoard(row+1, col, grid);
for(int num=1 + (int)(Math.random() * ((9 - 1) + 1)); num<=9; num++)
{
if(checkRow(row,num) && checkCol(col,num) && checkBox(row,col,num)){
grid[row][col] = num;
if(fillBoard(row+1, col, grid))
return true;
}
}
grid[row][col] = 0;
return false;
}
static public void main(String[] args){
fillBoard(0, 0, grid);
printGrid();
}
}
the problem is with generating numbers in fillBoard backtrack algorithm
it basically puts 0 everywhere
when I change the num range in for loop to 10 it goes smoothly but my numbers need to be lower than 9
i can also change the beginning of backtrack fillBoard to row==8 and col==8 and it fills it correctly with random numbers leaving last row and last column with "0".
how to generate random numbers from 1 to 9 and fill all my grid?
Try this :
public static void main(String[] args) {
int[][] grid = new int[9][9];
randomFillGrid(grid, 1, 10);
for (int[] row : grid) {
System.out.println(Arrays.toString(row));
}
}
static void randomFillGrid(int[][] grid, int randomNumberOrigin, int randomNumberBound) {
PrimitiveIterator.OfInt iterator = ThreadLocalRandom.current()
.ints(randomNumberOrigin, randomNumberBound)
.iterator();
for (int[] row : grid) {
for (int i = 0; i < row.length; i++) {
row[i] = iterator.nextInt();
}
}
}
EDIT :
if you want to generate a sudoku grid i.e.
the same single integer may not appear twice in the same row, column or in any of the nine 3×3 subregions of the 9x9 playing board.
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
/**
* #author FaNaJ
*/
public class SudokuGenerator {
private static final int N = 9;
private static final int S_N = 3;
public static int[][] generateSudokuGrid() {
int[][] grid = new int[N][N];
int[] row = {1, 2, 3, 4, 5, 6, 7, 8, 9};
for (int y = 0; y < N; y++) {
int attempts = 0;
do {
if (++attempts > 1000000) { // Oops! I know (sometimes :) it's not a good algorithm...
return generateSudokuGrid();
}
shuffleArray(row);
} while (!isAllowed(grid, y, row));
System.arraycopy(row, 0, grid[y], 0, N);
}
return grid;
}
static boolean isAllowed(int[][] grid, int y, int[] row) {
// check columns
for (int i = 0; i < y; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] == row[j]) {
return false;
}
}
}
// check sub grids
int startY = (y / S_N) * S_N;
for (int x = 0; x < N; x++) {
int startX = (x / S_N) * S_N;
for (int j = startX; j < startX + S_N; j++) {
if (j != x) {
for (int i = startY; i < y; i++) {
if (grid[i][j] == row[x]) {
return false;
}
}
}
}
}
return true;
}
static void shuffleArray(int[] array) {
Random random = ThreadLocalRandom.current();
for (int i = N; i > 1; i--) {
swap(array, i - 1, random.nextInt(i));
}
}
static void swap(int[] array, int i, int j) {
int tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
public static void main(String[] args) {
int[][] grid = generateSudokuGrid();
for (int[] row : grid) {
System.out.println(Arrays.toString(row));
}
}
}
output :
[3, 4, 6, 9, 1, 2, 7, 8, 5]
[9, 7, 2, 3, 8, 5, 4, 1, 6]
[5, 8, 1, 6, 7, 4, 3, 2, 9]
[7, 6, 3, 8, 2, 9, 1, 5, 4]
[4, 9, 5, 1, 6, 7, 2, 3, 8]
[2, 1, 8, 4, 5, 3, 6, 9, 7]
[6, 2, 4, 5, 9, 1, 8, 7, 3]
[8, 5, 7, 2, 3, 6, 9, 4, 1]
[1, 3, 9, 7, 4, 8, 5, 6, 2]
You can use Random class of java.utilpackage to generate random numbers. Below is an example that generates random numbers between 1 to 9:
Random rn = new Random();
int answer = rn.nextInt(9) + 1;
Before I start let me say that this while I'm not going tell you outright what all of your errors are, I will help you narrow your search and suggest a method to further debug your code.
Now to your problem: your array populated only with zero.
Only two lines can populate your array.
The first sets a spot in the array to have a random int value between 1 and 9 inclusive. If this random number doesn't pass a series of tests then that spot in the array is set to zero.
If one of these testers never returns true, the array will be populated with only zeros.
This leaves 4 functions that could be bugged.
-checkRow
-checkCol
-checkBox
-fillBoard
The first 2 functions are relatively simple so I can say with certainty that those work fine.
This leads only the checkBox and fillBoard functions under suspicion as causes of your bug.
At this point, this is where the debugging comes in.
Both of these functions contain loops.
One method to see if your loop is working is to compare a set of expected changes/return values to those which are actually gotten from the program.
To do this, either use a debugger
(assert statement + java -ea program.java and or other debugger methods)
Or, you could add print statements within your loop which print your gotten values for various variables/functions.
In any case, welcome to Stacks Overflow.
You mention that you are using a backtrack algorithm so I thought this would be fun to use a backtrack algorithm and try to demonstrate what it is. Below is a mash-up of your code and mine. I tried to stick to what you were doing and only add/change what I felt like I needed to.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* SudokuBoard.
*/
public class SudokuBoard {
// Dimension size of everything
static int N = 9;
// Sudoku grid
static int[][] grid = new int[N][N];
// Values that are potentially valid at each position in the sudoku grid
static int[][][] values = new int[N][N][N];
// Current index into the values
static int[][] index = new int[N][N];
/**
* Return a shuffled list of values from 1 - 9 with each value
* appearing only once.
*/
private static List<Integer> getValidValues(){
List<Integer> validValues = new ArrayList<>();
for(int i = 1; i < 10; i++){
validValues.add(i);
}
Collections.shuffle(validValues);
return validValues;
}
/**
* Populate the values array with shuffled values to choose from.
*/
private static void initValues()
{
for(int i = 0; i < values.length; i++){
for(int j = 0; j < values[i].length; j++){
List<Integer> validValues = getValidValues();
for(int k = 0; k < values[j].length; k++){
values[i][j][k] = validValues.get(k);
}
}
}
}
/**
* print the 2D sudoku grid.
*/
public static void printGrid()
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++) {
System.out.printf("%5d", grid[row][col]);
}
System.out.println("\n");
}
}
/**
* Check the row for validity.
*/
private static boolean checkRow(int row, int num)
{
for( int col = 0; col < 9; col++ )
if(grid[row][col] == num)
return false;
return true;
}
/**
* Check the col for validity.
*/
private static boolean checkCol(int col, int num)
{
for( int row = 0; row < 9; row++ )
if(grid[row][col] == num)
return false;
return true;
}
/**
* Check the box for validity.
*/
private static boolean checkBox(int row, int col,
int num, boolean testRowCol)
{
int theR = row;
int theC = col;
row = (row / 3) * 3;
col = (col / 3) * 3;
for(int r = 0; r < 3; r++) {
for (int c = 0; c < 3; c++) {
if (testRowCol) {
if (theR == row + r && theC == col + c){
continue;
}
}
if (grid[row + r][col + c] == num) {
return false;
}
}
}
return true;
}
/**
* Build the sudoku board.
*/
public static boolean fillBoard(int row, int col)
{
// if we are back at the beginning then success!
// but just for sanity we will check that its right.
if(row != 0 && col != 0){
if(row % 9 == 0 && col % 9 == 0){
return checkBoard();
}
}
// don't go out of range in the grid.
int r = row % 9;
int c = col % 9;
// get the index in the values array that we care about
int indexIntoValues = index[r][c];
// if the index is out of range then we have domain wipe out!
// lets reset the index and try to back up a step. Backtrack!
if(indexIntoValues > 8){
index[r][c] = 0;
// there are a few cases to cover
// if we are at the beginning and the index is out
// of range then failure. We should never get here.
if(row == 0 && col == 0) {
return false;
}
grid[r][c] = 0;
// if the row is at 0 then back the row up to row - 1 and
// the col - 1
if(r == 0 && c > 0) {
return fillBoard(row - 1, col - 1);
}
// if the row is greater than 0 then just back it up by 1
if(r > 0){
return fillBoard(row - 1, col);
}
}
index[r][c] += 1;
// get the value that we care about
int gridValue = values[r][c][indexIntoValues];
// is this value valid
if(checkRow(r,gridValue) && checkCol(c,gridValue) &&
checkBox(r,c,gridValue,false)){
// assign it and move on to the next one
grid[r][c] = gridValue;
return fillBoard(row+1, r == 8 ? col + 1 : col);
}
// the value is not valid so recurse and try the next value
return fillBoard(row, col);
}
/**
* This is a sanity check that the board is correct.
* Only run it after a solution is returned.
*/
private static boolean checkBoard(){
//the grid is N X N so just use N as the condition.
//check rows are ok.
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
//for each of the elements in the row compare against
//every other one except its self.
int toTest = grid[i][j];
//check that the digits in the elements are in the valid range.
if(toTest > 9 || toTest < 1)
return false;
for(int k = 0; k < N; k++){
//don't test me against myself
if(k == j)
continue;
//if i am equal to another in the row there is an error.
if(toTest == grid[i][k])
return false;
}
}
}
//check the cols are ok.
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
//flip i and j to go for cols.
int toTest = grid[j][i];
for(int k = 0; k < N; k++){
if(k == j)
continue;
if(toTest == grid[k][i])
return false;
}
}
}
//check blocks are ok
for(int i = 0; i < N; i++){
for(int j = 0; j < N; j++){
int toTest = grid[i][j];
if(!checkBox(i, j, toTest, true))
return false;
}
}
return true;
}
static public void main(String[] args){
initValues();
if(fillBoard(0, 0))
printGrid();
else
System.out.println("Something is broken");
}
}
So the main things that I added were two multidimensional arrays one is a values list, and the other is a current index into that values list. So the values array keeps a list of all of the valid values that each cell can have. I shuffled the values to give the random feel that you were looking for. We don't really care about value ordering here for any performance reasons, but we want it to be "random" in order to get a different board from run to run. Next the index array keeps track of where you are in the values array. At any point that your index in the index array goes out of bounds, that means that none of the values will work. This is the point that you need reset the index to zero and go back to the cell you came from to try a new value there. That is the backtracking step. I kept moving through the array sequential as you did but its not necessary. I think you could actually go to the variable that has the least amount of valid values, so the highest index in this case, and the search should be faster, but who cares right now, it's a small search, the depth is 81 and you win! I also included a sanity check that the board is valid.
Here is an output:
1 3 2 5 7 6 4 9 8
7 5 8 1 9 4 3 2 6
6 4 9 8 2 3 1 7 5
8 6 3 2 5 9 7 1 4
5 7 4 6 3 1 9 8 2
9 2 1 4 8 7 5 6 3
4 9 7 3 6 8 2 5 1
3 8 5 7 1 2 6 4 9
2 1 6 9 4 5 8 3 7
I hope this helps you in some way, this was a fun one.
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 wondering if someone could help me, I have a game where the computer generates a random 4 digit code, each digit ranging from 0-5. Then the user guesses this code and the computer returns an array that i print out to a string. The array should contain a 6 for every number in the guess that is the correct number in the correct place, a 7 for each number in the guess that is a correct number but wrong spot for it, and finally a 5 for any completely incorrect numbers.
Example,, if the code is: 0143
and the user's guess is: 0451
the array should be: 6775
This is because the 0 is completely correct, the 1 and 4 are in the code, but were guessed in the wrong spot, and the 5 is completely incorrect. Also each digit is in a separate part of the arrays.
This is what I have so far:
for (int i = 0; i < 4; i++) {
if (combo[i] == guess[i]) {
Pegs[peg] = 6;
peg++;
}
}
for (int i = 0; i < 4; i++) {
for (int x = 0; x < 4; x++) {
if (guess[i] == combo[x] && guess[i] != combo[i]) {
Pegs[peg] = 7;
peg++;
}
}
}
for (int i = 0; i < 4; i++) {
if (Pegs[i] == 0) {
Pegs[i] = 5;
}
}
The array guess stores the users guess, the array combo is the correct code, Pegs[] is where the compared array is stored, and the int peg just says where to store the value in the array. The problem with this is it doesn't always return the array correctly to what it to do.
With the other methods, you will get into troubles if you have a scenario where
int[] combot = new int[] {0, 1, 1, 3};
int[] guess = new int[] {0, 4, 5, 1};
as you'll get an incorrect [6, 7, 7, 5] instead of the correct [6, 7, 5, 5] because you'll count your last guess 1 in double.
By using two flags array, one for the exact matches and one for the misplaced guess a single flag array, you can achieve much better and accurate results :
** Edited ** I reverted it back because I have found that for combo = [0, 1, 1, 3] and guess = [3, 0, 1, 5], it was giving an incorrect response.
public int[] computeGuess(int[] combo, int[] guess) {
int[] result = new int[4];
Arrays.fill(result, 5); // incorrect values for all!
boolean[] exactMatches = new boolean[4]; // all initially set to false
boolean[] misplaced = new boolean[4];
for (int i = 0; i < 4; i++) {
if (combo[i] == guess[i]) {
exactMatches[i] = true;
misplaced[i] = false; // make sure we don't use this as misplaced
} else {
for (int j = 0; j < 4; j++) {
if (i != j && combo[i] == guess[j] && !exactMatches[j] && !misplaced[j]) {
misplaced[j] = true;
break;
}
}
}
}
int i = 0;
for (boolean b : exactMatches) {
if (b) {
result[i++] = 6;
}
}
for (boolean b : misplaced) {
if (b) {
result[i++] = 7;
}
}
return result;
}
To compare the array you need only the first loop and the inner loop should be executed only if the numbers at the same position are not equal:
for(int i = 0; i < 4; i++) {
Pegs[i]=5;
if(combo[i] == guess[i]) {
Pegs[i] = 6;
guess[i]= -1;
}
}
for(int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if(combo[i] == guess[j]) {
Pegs[i]=7;
guess[j]= -1;
break;
}
}
}
...