Compare elements of a matrix by java columns - java

I have the following code and the following doubt about the route of the column of a matrix, comparing with the previous one, later and others. I take the first column from top to bottom. I take the first element and compare if they are the same as the next one (below). This second position of the column, compares if they are the same with the one above and the one below, and so on with the third one. I mean, if I have this column:
1
2
2
2
3
2
2
2
2
1
If you have 3 or more identical contiguous numbers, I have to set them to 0 (that's what I think it would do). The output would be:
1
0
0
0
3
0
0
0
0
1
This I need to do with each column, I have this method and I want to do it in the simplest way, the most direct solution without strange things, although I'm thinking that it has to be recursive anyway, I do not know. The only thing that makes me is to create a matrix of zeros and I can not find the fault.
Code:
public static void matrix(int[][] matrix, int size, int[] color, int position) {
int repeated = 0;
for (int row = 1; row < size; row ++) {
for (int col = 1; col < size; col++) {
if (matrix[row][col] == matrix[row][col++]) {
repeated = matrix[row][col];
}
while (matrix[row][col] == repeated) {
matrix[row][col] = 0;
row++;
}
}
}

Here is the code I constructed for your scenario. You can find helpful comments within the code.
public static void main(String[] args)
{
int matrix[][] = new int[][]{
{1,2},
{2,2},
{2,2},
{2,2},
{3,2},
{2,2},
{2,2},
{2,3},
{2,1},
{1,3}};
matrix(matrix, 10, null, 0);
System.out.println(matrix);
}
public static void matrix(int[][] matrix, int size, int[] color, int position) {
//This value keeps track of the current value checked for repetition
int repeated = 0;
//The running total for repeated
int count = 1;
//My matrix create with 2 columns,
for (int col = 0; col < 2; col ++) {
//initialized - may need length check
repeated = matrix[0][col];
count = 1;
for (int row = 1; row < size; row++) {
if (matrix[row][col] == repeated)
{
count++;
}
else
{
//reset the values when match fails
count = 1;
repeated = matrix[row][col];
}
if(count == 3)
{
//First score of 3
matrix[row][col] = 0;
matrix[row-1][col] = 0;
matrix[row-2][col] = 0;
}
else if(count > 3)
{//Scoring after 3
matrix[row][col] = 0;
}
}
}
}
Here is the output
[[1, 0],
[0, 0],
[0, 0],
[0, 0],
[3, 0],
[0, 0],
[0, 0],
[0, 3],
[0, 1],
[1, 3]]

Related

How do we do sum of indexes in a 2D array

I have a 2D array where rows = 3 and columns = 2. I want to get a sum of all the indices. Here is my array.
arr[][] = [1, 2], [3, 4], [5, 6]
Row 1
At index (0, 0) the sum of indexes becomes (0 + 0 = 0)
At index (0, 1) the sum of indexes becomes (0 + 1 = 1)
Row 2
At index (1, 0) the sum of indexes becomes (1 + 0 = 1)
At index (1,1) the sum of indexes becomes (1 + 1 = 2)
Row 3
At index (2, 0) the sum of indexes becomes (2 + 0 = 2)
At index (2, 1) the sum of indexes becomes (2 + 1 = 3)
My expected output becomes
0 1 1 2 2 3
I am unable to find any resource, how to do this
Another quick example:
import java.util.*;
class Main {
public static void main(String[] args) {
int[][] arr = new int[3][2];
for(int row=0; row<arr.length; row++) {
for(int col=0; col<arr[row].length; col++) {
arr[row][col] = row + col;
}
}
for(int[] row : arr) {
System.out.println(Arrays.toString(row));
}
}
}
Output:
[0, 1]
[1, 2]
[2, 3]
You have to do sum of column and row using for loop or any other loop.
import java.util.*;
public class Main
{
public static void main(String[] args) {
int rows, cols, sumIndex = 0;
int a[][] = {
{1, 2},
{3, 4},
{5, 6}
};
rows = a.length;
cols = a[0].length;
for(int i = 0; i < rows; i++){
for(int j = 0; j < cols; j++){
sumIndex = i + j;
System.out.print(sumIndex + " ");
}
}
}
}

Filling a jagged 2d array first by columns

I want to write a function that takes an 2d array and fills it with 1...n but counting the columns first instead of the rows:
input = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};
the output should be: {{1, 5, 7, 8}, {2}, {3}, {4, 6}};
if i were to loop through rows and then colums i get:
private static void fill1(int[][] input) {
int count = 1;
for (int i = 0; i < input.length; i++) {
for (int j = 0; j < input[i].length; j++) {
input[i][j] = count;
count++;
}
}
}
How do I loop through colums first?
You can do this by first transposing your input, executing your fill1 code and then transposing the output again.
See this question for how to transpose a 2 dimensional array in Java: java multi-dimensional array transposing
If you were dealing with a regular 2d matrix, where all the rows had the same number of columns, the code would be a simple modification of the code for filling the matrix row-by-row:
private static void fill1(int[][] input) {
int count = 1;
for (int j = 0; j < input[0].length; j++) {
for (int i = 0; i < input.length; i++) {
input[i][j]= count;
count++;
}
}
}
The process is basically the same for a ragged 2d array, but with a couple added twists:
You need to do some extra work to figure out how many columns there could be (i.e., the maximum row length)
You need to be prepared for the case when there's no cell at a given row/column position.
The following modification of the previous code addresses these issues:
private static void fill1(int[][] input) {
int maxCols = input[0].length;
for (int i = 1; i < input.length; ++i) {
if (input[i].length > maxCols) {
maxCols = input[i].length;
}
}
int count = 1;
for (int j = 0; j < maxCols; j++) {
for (int i = 0; i < input.length; i++) {
if (j < input[i].length) {
input[i][j]= count;
count++;
}
}
}
}
To iterate first over the columns of a jagged 2d array to fill it, you have to know the maximum number of columns beforehand, but if you don't know that, you can iterate to the Integer.MAX_VALUE and check at each step if the columns are still present or not:
int[][] arr = {{0, 0, 0, 0}, {0}, {0}, {0, 0}};
int count = 1;
for (int col = 0; col < Integer.MAX_VALUE; col++) {
boolean max = true;
for (int row = 0; row < arr.length; row++) {
if (col < arr[row].length) {
arr[row][col] = count;
count++;
max = false;
}
}
if (max) break;
}
for (int[] row : arr) {
System.out.println(Arrays.toString(row));
}
Output:
[1, 5, 7, 8]
[2]
[3]
[4, 6]
See also: How do you rotate an array 90 degrees without using a storage array?
To populate a 2d array first by columns, you can use two nested streams. In case of a jagged 2d array, when you don't know beforehand the number of the columns in each row, in an outer stream you can traverse while the columns are still present.
/**
* #param arr array that should be populated.
* #return maximum row length, i.e. columns count.
*/
private static long populate(int[][] arr) {
AtomicInteger counter = new AtomicInteger(1);
return IntStream
// traverse through the array columns
.iterate(0, i -> i + 1)
// process the array rows where
// this column is present
.mapToLong(i -> Arrays.stream(arr)
// filter those rows where
// this column is present
.filter(row -> row.length > i)
// assign a value to the element and increase the counter
.peek(row -> row[i] = counter.getAndIncrement())
// count of rows where this column is present
.count())
// while the columns are still present
.takeWhile(i -> i > 0)
// max columns count
.count();
}
public static void main(String[] args) {
int[][] arr = {{0, 0, 0, 0, 0, 0}, {0, 0}, {0}, {0, 0, 0}};
System.out.println("Max columns count: " + populate(arr));
System.out.println(Arrays.deepToString(arr));
}
Output:
Max columns count: 6
[[1, 5, 8, 10, 11, 12], [2, 6], [3], [4, 7, 9]]
See also: How to create a new List from merging 3 ArrayLists in round robin style?

Dividing a 1D array into a 2D array

So I have homework that asked me to:
Write a method that takes two parameters: an array of integers and an integer that represents a number of elements. It should return a two-dimensional array that results from dividing the passed one-dimensional array into rows that contain the required number of elements. Note that the last row may have less number of elements if the length of the array is not divisible by the required number of elements. For example, if the array {1,2,3,4,5,6,7,8,9} and the number 4 are passed to this method, it should return the two-dimensional array {{1,2,3,4},{5,6,7,8},{9}}.
I tried to solve it using this code:
public static int[][] convert1DTo2D(int[] a, int n) {
int columns = n;
int rows = a.length / columns;
double s = (double) a.length / (double) columns;
if (s % 2 != 0) {
rows += 1;
}
int[][] b = new int[rows][columns];
int count = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
if (count == a.length) break;
b[i][j] = a[count];
count++;
}
}
return b;
}
But I had a problem which is when I try to print the new array this is the output:
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 0, 0, 0]]
So how can I remove the 3 zeros at the end? Just a note that I can't use any method from java.util.* or any built-in method to do this.
Change the 2D array's initialization to not contain the second dimension: new int[rows][]. Your array now has null arrays inside it. You have to initialize those in your loop: b[i]=new int[Math.min(columns,remainingCount)]; where remainingCount is the amount of numbers outside the 2d array.
Populating a 2d array with values from a 1d array as long as they are present:
public static int[][] convert1DTo2D(int[] arr, int n) {
// row count
int m = arr.length / n + (arr.length % n == 0 ? 0 : 1);
// last row length
int lastRow = arr.length % n == 0 ? n : arr.length % n;
return IntStream.range(0, m)
.mapToObj(i -> IntStream.range(0, i < m - 1 ? n : lastRow)
.map(j -> arr[j + i * n])
.toArray())
.toArray(int[][]::new);
}
public static void main(String[] args) {
int[] arr1 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int[][] arr2 = convert1DTo2D(arr1, 4);
System.out.println(Arrays.deepToString(arr2));
// [[1, 2, 3, 4], [5, 6, 7, 8], [9]]
}
See also: How to populate a 2d array with values from a 1d array?
It may be better to switch arguments in the method:
int[][] convert1DTo2D(int cols, int... arr)
to allow use of vararg.
Also, it is possible to iterate on the input array (single loop) instead of nested loops.
Example implementation:
public static int[][] convert1DTo2D(int cols, int... a) {
int lastRowCols = a.length % cols;
int rows = a.length / cols;
if (lastRowCols == 0) {
lastRowCols = cols;
} else {
rows++;
}
int[][] b = new int[rows][];
for (int i = 0; i < a.length; i++) {
int r = i / cols;
int c = i % cols;
if (c == 0) { // start of the row
b[r] = new int[r == rows - 1 ? lastRowCols : cols];
}
b[r][c] = a[i];
}
return b;
}
Adding this if-condition to your code will shorten the final array should it not be the right size:
...
final int[][] b = new int[rows][columns];
if ((a.length % columns) != 0) {
b[rows - 1] = new int[a.length % columns];
}
int count = 0;
...
% is the Modulo operator which gives you the remainder of a division of the first and second number.
9 % 4 would return 1, the exact size needed for our final array.
We then merely have to replace the final array with a new one of that size.

Finding the largest area of equal numbers in matrix java

I have a task.I need to find the biggest area with equal numbers(e.g. neighbours by row or column). The program that i made works fine,but the problem is that if i have the following matrix:
{ 1, 3, 2, 2, 2, 4 }
{ 3, 1, 3, 2, 4, 4 }
{ 4, 3, 1, 2, 3, 3 }
{ 4, 3, 1, 3, 3, 1 }
{ 4, 3, 3, 3, 1, 1 }
The program will print 10.Okay maybe some of you may say that it's because i add 1 to the final result,yeah that's true but if i don't add 1 ,and if the number at position [1][1] was 3 instead of 1 ,i would get 12 witch is wrong,so that`s why i add 1.So my question is do you have any suggestions about optimazing the algorithm..if yes,i would be very thankful to hear them :)..
Here is my code:
protected int counter = 0;
protected int max = 1;
protected enum eState {
Vi,
InPr,
Unvi
};
public void recNodeMatrix(int i, int j, eState st[][],int [][]matr,int n,int k) {
st[i][j] = eState.InPr;
for (int r = 0; r < n; r++) {
for (int c = 0; c < k; c++) {
if ((matr[i][j] == matr[r][c])
&& ((((i+j) - (r + c)) == 1) || (((i+j) - (r + c)) == -1))
&& ((st[r][c] == eState.Unvi))) {
counter++;
recNodeMatrix(r, c, st,matr,n,k);
}
}
}
st[i][j] = eState.Vi;
}
public void Zad17() {
int n=5,k=6;
eState st[][] = new eState[n][k];
int[][] matr = new int[][] {
{ 1, 3, 2, 2, 2, 4 },
{ 3, 1, 3, 2, 4, 4 },
{ 4, 3, 1, 2, 3, 3 },
{ 4, 3, 1, 3, 3, 1 },
{ 4, 3, 3, 3, 1, 1 } };
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
st[i][j] = eState.Unvi;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < k; j++) {
if(st[i][j] == eState.Unvi) {
recNodeMatrix(i, j, st,matr,n,k);
if(max<counter)
max=counter;
counter =0;
}
}
}
System.out.print(max+1);
}
Probably the best way to solve this problem is with a union-find data structure: https://en.wikipedia.org/wiki/Disjoint-set_data_structure
Initially, each cell is its own set, and then you merge the sets for every pair of adjacent cells that have equal numbers in them.
When you're done, the answer is the size of the biggest set. Since you have to keep track of the set sizes anyway, use union-by-size instead of union-by-rank.
Applying a bit of cleverness, you can implement the union-find with just an array of N*K integers -- one for each cell. Each integer is either the index of the parent set or -size for roots.
This solves the problem in about linear time, and will probably be faster in practice than flood-fill solutions using a similar amount of memory.

Filling array with random digits in range

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.

Categories

Resources