Java Sudoku brute force solver, how does it work? - java

So you find the code below here. Most of the code I understand, but there is one bit I don't. The place where we create the boolean array called digits and the bit after that 3 * (x / 3).
I think it's used to check if each square in the sudoku has 9 unique numbers as well, but I'm not sure on how I can explain this to let's say someone next to me.
Why do I need the array of boolean here? Can someone explain to me what it is doing and why?
Kind regards!
public int[][] solvePuzzle(int[][] matrix) {
int x, y = 0;
boolean found = false;
// First we check if the matrix contains any zeros.
// If it does we break out of the for loop and continue to solving the puzzle.
for (x = 0; x < 9; x++) {
for (y = 0; y < 9; y++) {
if (matrix[x][y] == 0) {
found = true;
break;
}
}
if (found) {
break;
}
}
// If the puzzle doesn't contain any zeros we return the matrix
// We now know that this is the solved version of the puzzle
if (!found) {
return matrix;
}
boolean digits[] = new boolean[11];
for (int i = 0; i < 9; i++) {
digits[matrix[x][i]] = true;
digits[matrix[i][y]] = true;
}
int boxX = 3 * (x / 3), boxY = 3 * (y / 3);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
digits[matrix[boxX + i][boxY + j]] = true;
}
}
// We loop over all the numbers we have to check if the next number fits in the puzzle
// We update the matrix and check recursively by calling the same function again to check if the puzzle is correct
// If it's not correct we reset the matrix field to 0 and continue with the next number in the for loop
for (int i = 1; i <= 9; i++) {
if (!digits[i]) {
matrix[x][y] = i;
if (solvePuzzle(matrix) != null) {
return matrix;
}
matrix[x][y] = 0;
}
}
// The puzzle can't be solved so we return null
return null;
}

I have added some explanation as comments inline:
//we need to know what digits are we still allowed to use
//(not used in this row, not used in this column, not used in
//the same 3x3 "sub-box")
boolean digits[] = new boolean[11];
//so we run through the rows/coumns around the place (x,y)
//we want to fill in this iteration
for (int i = 0; i < 9; i++) {
//take a used number from the row of x (matrix[x][i]) and mark it
// as used
digits[matrix[x][i]] = true;
//take a used number from the column of y (matrix[i][y]) and mark it
// as used
digits[matrix[i][y]] = true;
}
//find the top-left corner of the sub-box for the position (x,y) we
//want to fill in
//example: x is 8 -> 3 * 8/3 -> 6, so we start from 6
int boxX = 3 * (x / 3), boxY = 3 * (y / 3);
//iterate through the sub-box horizontally and vertically
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
//take a used number from the sub-box and mark it
// as used
digits[matrix[boxX + i][boxY + j]] = true;
}
}

There seem to be two issues you are unclear on:
The boolean array - this array is used to track which digits have been used already on a specific row or column. So imagine a row of tick boxes each with a digit written next to it (the array index) - these boxes are checked or unchecked to show a digit has been used or not.
The expressions 3* (x/3) and 3 * (y/3) - what you need to remember here is that this is integer division (that means the result of the division is always rounded down to an integer. For example if x=1 then 3 (x/3) is 3 (1/3) is 3 * (0) =0 (whereas if this was float division the result would be 3*(0.3333)=1. So these maths expressions essentially change you number to the next lowest multiple of three - that is 1 -> 0, 2 -> 0, 3 -> 3, 4 -> 3 etc.

Related

Why is the DP solution not working, Trapping Rain Water?

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.
example:
Input: height = [0,1,0,2,1,0,1,3,2,1,2,1]
Output: 6
Explanation: The above elevation map (black section) is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.
**Constraints**:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
The issue with this is that it is outputting 0 for when the input is [2,0,2] but the code should be setting the index 1 to have a leftMax of 2 and rightMax of 2 so 2-0=2 should be the output
class Solution {
public int trap(int[] height) {
if(height == null || height.length == 0){
return 0;
}
int ans = 0;
int size = height.length;
int[] leftMax = new int[size];
int[] rightMax = new int[size];
leftMax[0] = height[0];
for(int i = 1; i < size; i++){
leftMax[i] = Math.max(leftMax[i-1],height[i]);
}
rightMax[0] = height[size-1];
for(int i = size-2; i >= 0; i--){
rightMax[i] = Math.max(rightMax[i+1],height[i]);
}
for(int i = 1; i < size-1; i++){
ans+= Math.min(leftMax[i],rightMax[i])-height[i];
}
return ans;
}
}
The problem is that your rightMax initialization is wrong, it initializes "on the wrong side". It initializes the [0] which was probably copied from the leftMax section. But the leftMax then iterates from the left, the rightMax iterates from the right and therefore the rightmost index should be initialized. Note that you already initialized with the correct height index but for the wrong rightMax - it should look like:
rightMax[size-1] = height[size-1]
This previously worked because the very right was (probably) not part of a water trap and therefore its wrong value did not have any impact. But in the very simply case of 2,0,2 it is part of the trap and messed up the result.
Now the code properly calculates the two given samples:
System.out.println(trap(new int[] {0,1,0,2,1,0,1,3,2,1,2,1})); // 6
System.out.println(trap(new int[] {2,0,2})); // 2

How do you print a grid of asterisks using multidimensional arrays?

I am new to programming and I have an exercise that's killing me. How can you print a grid (5-by-6) which consists of asterisks alone? [Later on, these asterisks will have to be replaced by letters which are read in with StdIn.readInt() and a switch statement, but for now I at least need to understand how to print the grid]. I would appreciate any help so much!
More specifically, the grid should look like this:
//THIS ISN'T THE CODE; JUST AN ILLUSTRATION OF WHAT SHOULD BE PRINTED
0 1 2 3 4 5
0 * * * * * *
1 * * * * * *
2 * * * * * *
3 * * * * * *
4 * * * * * *
//I AM SUPPOSED TO START WITH SOMETHING LIKE THIS:
public class Grid {
static int X = 6;
static int Y = 7;
public static void main(String[]args) {
int [][] grid = new int [X][Y];
This could have been done in many ways, but this is my way of doing it:
When you want to print a grid, you have to use 2 nested for loops.
Let's see what happens when you use 2 nested for loops:
for(int i = 0; i < 6; i++){
for(int j = 0; j < 7; j++){
}
}
We start with the first loop:
for i = 0, we will enter the second loop and iterate from 0 to 6.
for i = 1, we will enter the second loop and iterate from 0 to 6.
...
for i = 5, we will enter the second loop and iterate from 0 to 6.
What you should notice is that j will iterate and take values from 0 to 6 with each value of i.
Going back to your question, and comparing it by what i just showed, you should notice that for each line, you are printing 7 values (of a column).
Let's assume i is the number of lines, and j is the index of each value in that line (column).
public static void printGrid() {
for (int i = 0; i < 6; i++) {
System.out.println();
for (int j = 0; j < 7; j++) {
System.out.print("*");
}
}
}
This code prints on each line (i), 7 asterixes (j).
And each time i is incrementing, we are going back to the next line System.out.println(). That's why we put it inside the for loop with i.
In your situation, we have to tweak this code a little bit to be able to print the numbers on the sides, and that space at the top left corner.
The explanation is in the comments in my code.
public class Question_55386466{
static int X = 6;
static int Y = 7;
public static void printGrid() {
System.out.print(" "); // Printing the space on the top left corner
for (int i = 0; i < X; i++) {
if (i > 0) { // Printing the numbers column on the left, taking i>0 to start from the second line (i == 1)
System.out.println(); // Going to the next line after printing the whole line
System.out.print(i - 1);//Printing the numbers of the column. Taking i-1 because we start the count for i == 1 not 0
}
for (int j = 0; j < Y; j++) {
if (i == 0)
System.out.print(j + " ");//Print the first line numbers.
else
System.out.print(" * "); //if the line isn't the first line(i == 0), print the asterixes.
}
}
}
You can always edit the values of X and Y and get the desired result.
And later you can give this method your array as a parameter and print each element instead of the asterixes.

Find All Possible Paths Algorithm

Hello there StackOverFlow! I am posting here today because I have a problem here in Java where I am trying to compute the all the possible combinations of pogo sticks that my character may use to move. The character uses pogo sticks which all have a distance, given by user input.
Likewise, the total distance is also given via user input and all possible paths are to be found. I have shown my function below with the output and the desired output that I can't seem to get quite right.
I have been stuck on this problem for a while and I am really hoping somebody can help me out here!
/*
* First integer in input
*/
int totalDistance;
/*
* The remaining integers in the input
*/
ArrayList<Integer> pogoSticks = new ArrayList<Integer>();
private void findPaths() {
ArrayList<ArrayList<Integer>> possibleSticks = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < pogoSticks.size(); i++) {
int pogoStickDistance = pogoSticks.get(i);
if (pogoStickDistance == totalDistance) {
if (!possibleSticks.contains(new ArrayList<Integer>(pogoStickDistance))) {
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(pogoStickDistance);
possibleSticks.add(list);
}
} else if (pogoStickDistance < totalDistance) {
int remainingDistance = totalDistance;
ArrayList<Integer> possibleSubSticks = new ArrayList<Integer>();
possibleSubSticks.add(pogoStickDistance);
remainingDistance -= pogoStickDistance;
for (int j = 0; j < pogoSticks.size(); j++) {
int pogoStickDistance1 = pogoSticks.get(j);
if (pogoStickDistance1 == remainingDistance) {
possibleSubSticks.add(pogoStickDistance1);
possibleSticks.add(possibleSubSticks);
break;
} else if (pogoStickDistance1 < remainingDistance) {
possibleSubSticks.add(pogoStickDistance1);
remainingDistance -= pogoStickDistance1;
}
if (j == (pogoSticks.size() - 1) && pogoStickDistance1 != remainingDistance) {
j = 0;
}
}
}
}
System.out.println(possibleSticks);
}
Here is the output that I get from running the function above:
Enter input: 5 10 4 1 2
[[4,1], [1,4], [2,1,2]]
Note that 5 is the distance, and 10, 4, 1, and 2 are the distances that a pogo stick may travel.
The issue is that these are not all the possible paths! For example, it is missing the paths such as [1, 1, 1, 1, 1] or [2, 2, 1].
Can anybody please help me modify my function to include these? I believe it is happening because once my loop finds the first occurrence of a pogo stick distance that's less than the remaining distance it will immediately use that path and ignore other possibilities.
for(int i = 0;i < pogoSticks.size();i++){
//part to calculate small enough
int[] temps = new int[pogoSticks.size];
int temp1 = 0;
for(int j; j< pogoStricks.size();i++){
if(pogoSticks.getIndex(j) + k <= totalDisatnce){
temps[temp1] = pogoSticks.getIndex(j);
}
//code to calculate number of paths to get to TotalDistance
This should do half the job, now you just need a method to calculate the distance from all the temps variables. I suggest you subtract each value from the TotalDistance and see which numbers added up would equal that.

Searching a grid recursively by triangular numbers

I have a 36x25 grid of nodes that I wish to search through all triangular numbers from the corner opposite of the hypotenuse. Here's psuedocode for what I was considering, but this method only works until it hits the next corner of the grid, and I'm sure there is a much simpler way to do this recursively, I just am having difficulty figuring it out.
for(int iteration; iteration < maxDistance(49); iteration++)
{
int xAdd = iteration;
int yAdd = 0;
while(xAdd != 0)
{
checkStuff(nodeGrid[x+xAdd][y+yAdd]);
xAdd--;
yAdd++;
}
}
What I want program to do:
[0][1][2][3][4][5]
[1][2][3][4][5][6]
[2][3][4][5][6][7]
[3][4][5][6][7][8]
[4][5][6][7][8][9]
check in this order. So first check all tiles with value 0, then 1 and so on.
Note: in this case my function will only work up until the 4th set up tiles. Any further and it will reach out of bounds.
/**
* Only works for rectangular arrays
*/
public void iterateOver(Node[][] a){
int x_dim = a[0].length;
int y_dim = a.length;
for (int i = 0; i < x_dim + y_dim - 1; i++){
int x, y;
if (i < x_dim){
x = i;
y = 0;
}
else{
x = x_dim - 1;
y = i - x_dim + 1;
}
for (;x >=0 && y < y_dim; y++, x--){
doStuff(a[y][x]);
}
}
}
How it works
Picture your rectangular array:
[0][1][2][3][4][5]
[1][2][3][4][5][6]
[2][3][4][5][6][7]
[3][4][5][6][7][8]
[4][5][6][7][8][9]
There are clearly 6 columns and 5 rows (or 6 x values and 5 y values). That means that we need to do 6 + 5 - 1 iterations, or 10. Thus, the for (int i = 0; i < x_dim + y_dim - 1; i++). (i is the current iteration, measured from 0).
We start by columns. When i is less than the x dimension, x = i and y = 0 to start with. x is decremented and y is incremented until x is less than zero or y is equal to the y dimension. Then, we do a similar thing down the right hand side.

Android - Compute times a two numbers appear in cell number

Could anyone help me. I am trying to compute the number of times certain numbers appear in a table layout row - vertically and Horizontally, in other words. I would like to fill an array of numbers between say (4 and 5) to make it so that the number say 4 appears only 4times and 5 only twice (vertically & Horizontally) in say 6 * 6..take note
How can I work with any of this?
public boolean hasRepeatedNumbers(int[] x) {
int[] y = new int[x.length];
System.arraycopy(x, 0, y, 0, y.length);
Array.sort(y);
int i;
for (i = 1; i < y.length; i++) {
if (y[i] == y[i-1]) return true;
}
return false;
}
or
private int[] calculateUsedCells(int x, int y) {
int c[] = new int[2];
// horizontal
for (int i = 0; i < 2; i++) {
if (i == y)
continue;
int t = getCell(x, i);
if (t != 0)
c[t - 1] = t;
}
}
Any advice would be great, thanks.
Consider taking an int array and increase the element in the array at index of the value in the cell, at the end check the values in the array. You will get the number of times each number appeared.
Ex:
Number 4 has appeared in 1, 2, 5, 6 cells
array[content of the cell]++;
So at the end array[4] gives the number of times 4 appeared.

Categories

Resources