The following code i wrote to solve a sudoku. I am experiencing an unexpected behavior here. I am calling the displaySudokuBoard twice. one from inside sudokuFiller when i value becomes greater then 8(i am getting the solved sudoku array) and another call from main function(It return me the same array which was given as input).
Why i am getting different values of my array. what is wrong with the code
class SudokuSolver {
public int[][] sudokuBoard = {{2, 0, 0, 0, 0, 1, 0, 3, 8},
{0, 0, 0, 0, 0, 0, 0, 0, 5},
{0, 7, 0, 0, 0, 6, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 1, 3},
{0, 9, 8, 1, 0, 0, 2, 5, 7},
{3, 1, 0, 0, 0, 0, 8, 0, 0},
{9, 0, 0, 8, 0, 0, 0, 2, 0},
{0, 5, 0, 0, 6, 9, 7, 8, 4},
{4, 0, 0, 2, 5, 0, 0, 0, 0}};
private boolean checkNumberExistInRow(int i, int cellVals) {
for(int j = 0; j < 9; j++) {
if(sudokuBoard[i][j] == cellVals) {
return false ;
}
}
return true;
}
private boolean checkNumberExistInColumn(int j, int cellVals) {
for(int i = 0; i < 9; i++) {
if(sudokuBoard[i][j] == cellVals) {
return false;
}
}
return true;
}
private boolean checkNumberExistInGrid(int i, int j, int cellVals) {
i = (i / 3) * 3 ;
j = (j / 3) * 3;
for(int k = 0; k < 3; k++) {
for(int s = 0; s < 3; s++) {
if(sudokuBoard[i+k][j+s] == cellVals) {
return false;
}
}
}
return true;
}
private void FillNext(int i, int j) {
if(j < 8 ) {
sudokuFiller(i, j+1);
} else {
sudokuFiller(i+1, 0);
}
}
public void sudokuFiller (int i, int j) {
int k = 0;
if(i > 8) {
displaySodukoBoard();
return;
}
if(sudokuBoard[i][j] != 0) {
FillNext(i, j);
}
else {
for(int cellVals = 1; cellVals <= 9; cellVals++) {
if((checkNumberExistInRow(i, cellVals)) && (checkNumberExistInColumn(j, cellVals)) && (checkNumberExistInGrid(i, j, cellVals))) {
this.sudokuBoard[i][j] = cellVals;
FillNext(i,j);
}
}
this.sudokuBoard[i][j] = 0;
}
}
public void displaySodukoBoard() {
for(int row = 0; row < 9; ++row) {
for(int col = 0; col < 9; ++col) {
if ((col == 3) || (col == 6)){
System.out.printf("\t");
}
System.out.printf("%d ",sudokuBoard[row][col]);
}
if ((row == 2) || (row == 5)){
System.out.printf("\n");
}
System.out.print("\n");
}
}
}
class FeedMeASudoku {
public static void main(String[] args) {
SudokuSolver mySudokuSolver = new SudokuSolver();
mySudokuSolver.sudokuFiller(0,0);
System.out.print("\n");
mySudokuSolver.displaySodukoBoard();
}
}
Here is the problem: this.sudokuBoard[i][j] = 0;.
At the end of a set-process, you reset the field to 0 (sudokuFiller(int i, int j), else-statement, last line).
EDIT: this solves a part of the problem. The first three rows are now correctly displayed. However, the recursion does break preemptively. Now you need to debug your code further.
I assume you are trying to show the board first and then display the result of the new board which is your solution. The calculation was fine, but the order of calls was wrong.
In your Main() call, switch the second and fourth lines:
SudokuSolver mySudokuSolver = new SudokuSolver();
mySudokuSolver.displaySodukoBoard();
System.out.print("\n");
mySudokuSolver.sudokuFiller(0,0);
Also, as others suggested, you should learn how to debug and look for suggestions from LINT. For instance, you have unused variable int k = 0;
Related
I am making a snake game where the snake crosses through a 2D int array as its terrain. The values stored in the 2D array represent the time in seconds it takes to cross.
For example,
int[][] MAP = {
{ 1, 1, 1, 2, 2 },
{ 1, 2, 2, 2, 2 },
{ 3, 2, 2, 3, 1 },
{ 1, 1, 3, 2, 1 },
{ 1, 1, 3, 2, 1 }
};
So going from map[0][0] to map[0][4] takes 1 + 1 + 2 + 2 seconds. How would I make an algorithm that would find the shortest possible path for a snake to travel from position map[startX][startY] to map[endX][endY]?
This isn't a homework assignment, I'm just making a game for fun and would like to learn how to do this.
This is one is kinda known problem when discussing "dynamic programming", and even resembles an old post.
Still, I didn't find a solution that also prints the shortest path, so:
public class FastestPathCalculator {
private final int[][] map;
public FastestPathCalculator(int[][] map) {
this.map=map;
}
public static void main(String[] args) {
int[][] map = new int[][]{
{1, 1, 1, 4, 2},
{1, 2, 5, 2, 2},
{3, 2, 2, 3, 1},
{1, 1, 3, 2, 1},
{3, 1, 3, 2, 1}
};
FastestPathCalculator c = new FastestPathCalculator(map);
boolean[] result = c.computeFastestPath(map);
c.printPath(result);
}
Here, the boolean array represents the steps taken from (0,0) to (4,4). A value of TRUE means the step is to the right, FALSE means go down.
In this example, the array has 8 cells.
public boolean[] computeFastestPath(int[][] map) {
int pathLength = map.length + map[0].length - 2;
boolean[] result = new boolean[pathLength];
int[][] mapOfMinimalSums = buildMapOfMinimalSums();
int x = map.length-1;
int y = map[0].length-1;
for (int i = pathLength - 1 ; i >= 0; i--) {
if (x == 0)
result[i] = true;
else if (y == 0)
result[i] = false;
else if (mapOfMinimalSums[x][y] == map[x][y] + mapOfMinimalSums[x][y-1]) {
result[i] = true;
y--;
}
else {
result[i] = false;
x--;
}
}
return result;
}
public void printPath(boolean[] result) {
String[][] newPath = new String[map.length][map[0].length];
int x = 0;
int y = 0;
newPath[x][y] = String.valueOf(map[x][y]);
for (int i = 0 ; i < result.length; i++) {
if (result[i]) {
y++;
} else {
x++;
}
newPath[x][y] = String.valueOf(map[x][y]);
}
for (int i = 0 ; i < map.length; i++) {
for (int j = 0 ; j < map[0].length; j++) {
if (newPath[i][j] == null) {
System.out.print(" , ");
} else {
System.out.print(newPath[i][j] + ", ");
}
}
System.out.println();
}
System.out.println();
}
private int[][] buildMapOfMinimalSums() {
int[][] mapOfSums = new int[map.length][map[0].length];
for (int i = 0 ; i < map.length; i++) {
for (int j = 0 ; j < map[0].length; j++) {
if (i == 0 && j == 0)
mapOfSums[i][j] = map[i][j];
else if (i == 0) {
mapOfSums[i][j] = mapOfSums[i][j - 1] + map[i][j];
}
else if (j == 0)
mapOfSums[i][j] = mapOfSums[i-1][j] + map[i][j];
else
mapOfSums[i][j] = Math.min(mapOfSums[i-1][j], mapOfSums[i][j-1]) + map[i][j];
}
}
return mapOfSums;
}
}
I'm making a Sudoku solver which tries every possible value in a square and backtracks if it doesn't lead to a solution. I believe I have a nearly-working algorithm, but it only has worked so far on rows 0, 2, and 3 of a 16-cell puzzle.
public boolean fillBoard(int[][] board, int row, int col){
int index = 1; //Next value to try when an empty is found
boolean solved = false;
for(int i = row; i < width; i++){ //For each row
for(int j = col; j < height; j++){ //For each column
if(board[i][j]==0){ //0 represents empty
while(!solved){
board[i][j] = index;
if(checker.checkRow(board[i])
&& checker.checkColumn(columnToArray(board, j))
//&& checker.checkBox(<input>)
){
solved = fillBoard(board, i, 0);
}else{
if(index < width){
index++;
}else{
return false;
}
}
}
}
}
}
puzzle = copyPuzzle(board);
return true;
}
Right now it doesn't check for the third Sudoku rule, it only checks for columns and rows. However, it should still return a puzzle that follows the row and column rules, right? And once the checkBox method is written, it should just be able to solve the puzzle. Where did I mess up here?
EDIT with a few examples:
For an input of
{1, 2, 0, 0},
{0, 4, 0, 0},
{0, 0, 1, 0},
{0, 0, 3, 2}
The program returns
1 2 4 3
4 4 4 4
2 3 1 4
4 1 3 2
For an input of
{1, 0},
{2, 0}
It solves it correctly.
For an input of
{ 1, 0, 3, 4, 0, 0 },
{ 4, 0, 6, 0, 0, 3 },
{ 2, 0, 1, 0, 6, 0 },
{ 5, 0, 4, 2, 0, 0 },
{ 3, 0, 2, 0, 4, 0 },
{ 6, 0, 5, 0, 0, 2 }
It returns the puzzle unsolved
EDIT: checkRow for those who have asked
public boolean checkRow(int[]row){
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0; i < row.length;i++){
if(!set.add(row[i]) && row[i]>0){//Duplicate?
return false;
}
}
return true;
}
The issue was that it didn't reset the space to 0 when the value was incorrect, so if it ever reached the max index and wasn't correct, it just left it. The below code works. Just waiting on another person in my group to deliver the box-checking method, but I will probably end up having to do that myself.
public boolean fillBoard(int[][] board, int row, int col){
int index = 1; //Next value to try when an empty is found
boolean solved = false;
for(int i = row; i < width; i++){ //For each row
for(int j = col; j < height; j++){ //For each column
if(board[i][j]==0){ //0 represents empty
while(!solved){ //While the puzzle is unsolved
board[i][j] = index; //Try to fill with index
if(checker.checkRow(board[i])
&& checker.checkColumn(columnToArray(board, j))
//&& checker.checkBox(<input>)
){
solved = fillBoard(board, i, 0); //Next space
}
if(!solved) board[i][j] = 0;
if(index < width){
index++;
}else{
return false;
}
}
}
}
}
puzzle = copyPuzzle(board);
return true;
}
Currently I'm working on a program that generates random 0's and 1's in a 8x8 2D array board. What I have to do is check whether or not if all the numbers on the diagonal are the same (starting from the corners, not just any diagonals).
example:
int[][] array = {
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 1, 0}
};
So if by chance all the numbers starting from the top left corner (0,0),(1,1)...(7,7) are all either 0's or 1's then I have to output to the scanner indicating that "There is a major diagonal of 0" (from the example above).
Also from this example, we can see that from the top-right, the number "1" is repeated diagonally towards the bottom left, then I also have to display "There is a minor diagonal of 1".
So far I have figured out how to generate and input the numbers into the array, but I don't know how to check. This is what I have so far:
public class JavaTest{
// Main method
public static void main(String[] args) {
int[][] array = {
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 1, 0}
};
// Print array numbers
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++)
System.out.print(array[i][j] + " ");
System.out.println();
}
// Print checkers
checkMajorDiagonal(array);
}
// Check major diagonal
public static void checkMajorDiagonal(int array[][]) {
int majDiag;
boolean isMatching = true;
int row = 0;
for(row = 0; row < array.length; row++){
majDiag = row;
if(array[row][row] != array[row+1][row+1]){
isMatching = false;
break;
}
}
//If all elements matched print output
if(isMatching)
System.out.println("Major diagonal is all " + array[row][row]);
}
}
Though what I have so far is not working as I want it to be as there is an error, and I still have to do the minor diagonal. Thanks in advance.
There are a bunch of answers already. Here is one more way to do it. You are on the right track, but there is no need to complicate things by checking a diagonal element with the next element and so on. Just check each diagonal element with the first diagonal element. The moment you find a difference, you stop checking!
public static void checkDiagonal(int[][] array){
// Start with the assumption that both diagonals are consistent.
boolean majorConsistent = true;
boolean minorConsistent = true;
int length = array.length;
int tempMajor = array[0][0]; // all elements in the Major must be equal to this
int tempMinor = array[0][length-1]; // all elements in the Minor must be equal to this
// Check major diagonal, and update the boolean if our assumption is wrong.
for(int i=0; i<length; i++){
if (array[i][i] != tempMajor) { //(0,0);(1,1);(3,3);...
majorConsistent = false;
break;
}
}
// Check minor diagonal, and update the boolean if our assumption is wrong.
for(int i=0,j=length-1; i<length; i++,j--){
if (array[i][j] != tempMinor) { //(0,7);(1,6);(2,5);...
minorConsistent = false;
break;
}
}
System.out.println("Major elements all same = "+majorConsistent);
System.out.println("Minor elements all same = "+minorConsistent);
}
This way you are still doing both the checks in O(n) and you don't need nested for loops! Note that you can refine this code to remove redundancy i.e. have a single for loop, etc.
If you are using Java 8 then you could potentially do this with streams rather than iterating through the values manually. That might be a more direct approach than checking against previous values.
if (IntStream.range(0, size).map(n -> array[n][n]).allMatch(n -> n == 0)) {
}
if (IntStream.range(0, size).map(n -> array[n][size-n-1]).allMatch(n -> n == 1)) {
}
The error probably comes from the fact that you loop while row < array.length but you index into array[row+1]. This will result in an out of bounds exception.
For checking the minor diagonal, try something similar:
int maxIndex = array.length - 1;
for(row = 0; row < maxIndex; row++){
majDiag = row;
if(array[row][maxIndex - row] != array[row+1][maxIndex - (row+1)]){
isMatching = false;
break;
}
}
Some points about your method checkMajorDiagonal :
int majDiag;
boolean isMatching = true;
int row = 0;
for(row = 0; row < array.length; row++){
majDiag = row; //not being used anywhere
if(array[row][row] != array[row+1][row+1]){ //out of bounds with row+1
isMatching = false;
break;
}
}
You can remove the unused majDiag variable and change the loop code as
for(row = 0; row < array.length-1; row++)
Minor diagonal logic :
for(row = 0; row < array.length; row++){
for(col = 0; col < array[i].length; col++){
if(row+col==array[i].length){
array[row][col] // this would be your minor diagonal element row wise
}
}
int diagonalValue = 0;
for(int i = 0; i < 8 ; i++){
diagonalValue = array[i][j];
for(int j = 0; j < 8 ; j++)
if(i==j){
if(array[i][j]==diagonalValue){
counter++;
}
else
break;
}
}
}
if(counter==8) // yes they are same else not
keep size of array i.e. 9 in a variable to make it loosely coupled.
So I was working on this Sudoku solver in Java for few days now, and while it seemed to work, after I ran it on more difficult sudokus, it just crashes sometimes.
The solver itself is not of brute force nature. It was inspired by Knuth's Algorithm X. So I have a huge matrix of 0s and 1s which the algorithm tries to completely reduce and by doing that, solve the sudoku.
The procedure kinda goes like this:
is the matrix of 0s and 1s empty?
if not seek the column with least ones
pick a random row there
for every column in that row where there is 1, remove that column
remove that row
repeat on the reduced matrix
Now the algorithm will always find the solution when it starts removing the right columns and rows, and will always manage to solve the easy problems. I suspect that is because the matrix it has to reduce is pretty small (matrix of possibilities to fill the blanks) and therefore there is less chance it will have to backtrack (rebuild the matrix in case wrong rows have been removed).
I have been trying for several days now, to fix the part where the matrix gets repaired since that seemed to be the problem for it to crash on hard puzzles. But after (it seemed) I fixed that, there is something impossible happening and i dont know why - the program seems to eliminate all the possibilities to solve the puzzle. Do not be scared by the amount of code, the methods before the comment line "//algorithm X" work and aren't part of the problem. Only lines below.
That should be impossible since one of the columns with the least ones will ALWAYS be part of the solution but somehow it identifies all of them as invalid...
I commented the code and put all of it into a single .java file, so you can feel free to run and try it out. There are 3 sudokus i was testing it on - "sudoku" (easy, mostly correct), "sudoku1" hard, mostly fails, "sudoku3" empty, solved always with random solution.
In the beginning of program, im also using "myFakeRandomGenerator" since I wanted random row selection to always go same path for easier debugging.
For easier understanding of how i use the HashMaps in the program, im linking the python program that inspired what i wrote so far:
http://www.cs.mcgill.ca/~aassaf9/python/algorithm_x.html
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
public class Sudoku {
public static ArrayList<int[]> coverageMatrix = new ArrayList();
public static HashMap<String, ArrayList<Integer>> rowsMatrix = new HashMap<>();
public static HashMap<Integer, ArrayList<String>> columnsMatrix = new HashMap<>();
public static HashMap<String, HashMap<Integer, ArrayList<String>>> backupMonster = new HashMap<String, HashMap<Integer, ArrayList<String>>>();
public static ArrayList<Integer> invalidColumns = new ArrayList<Integer>();
public static ArrayList<String> invalidRows = new ArrayList<String>();
public static ArrayList<String> solution = new ArrayList<String>();
public static Random myFakeRandomGenerator = new Random(152);
public static void main(String[] args) {
//just rename the one you want to run into "sudoku" and off you go
int[][] sudoku = {
{5, 3, 0, 0, 7, 0, 0, 0, 0},
{6, 0, 0, 1, 9, 5, 0, 0, 0},
{0, 9, 8, 0, 0, 0, 0, 6, 0},
{8, 0, 0, 0, 6, 0, 0, 0, 3},
{4, 0, 0, 0, 0, 0, 0, 0, 1},
{7, 0, 0, 0, 0, 0, 0, 0, 6},
{0, 6, 0, 0, 0, 0, 0, 8, 0},
{0, 0, 0, 4, 1, 0, 0, 0, 5},
{0, 0, 0, 0, 8, 0, 0, 7, 9}
};
int[][] sudoku2 = {
{8, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 3, 6, 0, 0, 0, 0, 0},
{0, 7, 0, 0, 9, 0, 2, 0, 0},
{0, 5, 0, 0, 0, 7, 0, 0, 0},
{0, 0, 0, 0, 4, 5, 7, 0, 0},
{0, 0, 0, 1, 0, 0, 0, 3, 0},
{0, 0, 1, 0, 0, 0, 0, 6, 8},
{0, 0, 8, 5, 0, 0, 0, 1, 0},
{0, 9, 0, 0, 0, 0, 4, 0, 0}
};
int[][] sudoku3 = {
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},};
//we parse the input sudoku into string which is later turned into the giant complete coverage matrix
fillTheMatrix(parseSudoku(sudoku));
//here we just transform the giant matrix into the HashMap since it helps us with solving
rowsMatrix = matrixToRowValuesDict(coverageMatrix);
//we include the already given numbers of the sudoku into the solution
solution = addGivenNumbersToSolution(rowsMatrix);
//we generate the matrix of all possible entries for cells for algorithm X to run on
suggestValidMissingLines(parseSudoku(sudoku));
//since we re-generate both matrices because it was slightly altered above
rowsMatrix = matrixToRowValuesDict(coverageMatrix);
columnsMatrix = matrixToValueRowsDict(rowsMatrix);
//here we run the algoritm
solution = solve(rowsMatrix, columnsMatrix, solution);
parseSolution(solution, rowsMatrix);
drawSudoku(parseSolution(solution, rowsMatrix));
}
// <editor-fold desc="Sudoku parsing methods, working.">
public static ArrayList<String> addGivenNumbersToSolution(HashMap<String, ArrayList<Integer>> rowsMatrix) {
ArrayList<String> solutions = new ArrayList<String>();
for (String key : rowsMatrix.keySet()) {
solutions.add(key);
}
return solutions;
}
public static String parseSudoku(int[][] sudoku) {
String sudokuString = "";
for (int i = 0; i < sudoku.length; i++) {
for (int j = 0; j < sudoku[i].length; j++) {
if (sudoku[i][j] == 0) {
sudokuString += ".";
} else {
sudokuString += sudoku[i][j];
}
}
}
return sudokuString;
}
public static void fillTheMatrix(String sudoku) {
for (int i = 0; i < sudoku.length(); i++) {
placeInCell(i, sudoku.substring(i, i + 1));
}
}
public static void placeInCell(int index, String value) {
int[] cells = new int[81];
int[] rows = new int[81];
int[] columns = new int[81];
int[] boxes = new int[81];
int[] matrixRow = new int[324];
if (value.matches("[1-9]")) {
//this helps us place the number in the array
int arrayIndex = Integer.parseInt(value);
//we fill the first quarter of the matrix row - cells
cells[index] = 1;
//we fill the second quarter of the matrix row - rows
int multiplier = index / 9;
int rowsPosition = 9 * multiplier + arrayIndex - 1;
rows[rowsPosition] = 1;
//we fill the third quarter of the matrix row - columns
int colsPosition = index % 9 * 9 + (arrayIndex - 1);
columns[colsPosition] = 1;
//we fill the final quarter of the matrix row - boxes
int column = index % 9;
int row = index / 9;
int reducedColumn = column / 3;
int reducedRow = row / 3;
int boxNumber = reducedColumn + (reducedRow * 3);
int boxIndex = boxNumber * 9 + (arrayIndex - 1);
boxes[boxIndex] = 1;
matrixRow = mergeTheArrays(cells, rows, columns, boxes);
coverageMatrix.add(matrixRow);
}
}
//helper method for creating the single line of the giant matrix
public static int[] mergeTheArrays(int[] cells, int[] rows, int[] columns, int[] boxes) {
int[] merged = new int[324];
int mergedIndex = 0;
for (int i = 0; i < cells.length; i++) {
merged[mergedIndex] = cells[i];
mergedIndex++;
}
for (int i = 0; i < rows.length; i++) {
merged[mergedIndex] = rows[i];
mergedIndex++;
}
for (int i = 0; i < columns.length; i++) {
merged[mergedIndex] = columns[i];
mergedIndex++;
}
for (int i = 0; i < boxes.length; i++) {
merged[mergedIndex] = boxes[i];
mergedIndex++;
}
return merged;
}
public static String parseSolution(ArrayList<String> solution, HashMap<String, ArrayList<Integer>> rowsMatrix) {
//our final output
int[] numbers = new int[81];
String sudoku = "";
for (String key : solution) {
int index = (rowsMatrix.get(key).get(0));
int value = (rowsMatrix.get(key).get(2)) % 9 + 1;
numbers[index] = value;
}
for (int i = 0; i < numbers.length; i++) {
sudoku += numbers[i];
}
return sudoku;
}
public static void drawSudoku(String sudoku) {
System.out.print("+-------+-------+-------+\n");
for (int i = 0; i < 81; i += 9) {
System.out.print("| ");
for (int j = 0; j < 9; j++) {
System.out.print(sudoku.charAt(i + j) + " ");
if (j == 2 || j == 5 || j == 8) {
System.out.print("| ");
}
if ((i == 18 || i == 45 || i == 72) && j == 8) {
System.out.print("\n+-------+-------+-------+");
}
}
System.out.println("");
}
}
public static void suggestValidMissingLines(String sudoku) {
for (int i = 0; i < sudoku.length(); i++) {
//we find empty slots
if (sudoku.substring(i, i + 1).equals(".")) {
Set unitValues = new HashSet();
unitValues.addAll(checkAllColumnPreerValues(i, sudoku));
unitValues.addAll(checkAllRowPeerValues(i, sudoku));
//unitValues.addAll(checkAllBoxPeerValues4x4(i, sudoku));
//we go through values 1-9 and if that value ISN'T in any peer cell, we add the suggestion for that value
for (int j = 1; j < 10; j++) {
if (!unitValues.contains(j + "")) {
placeInCell(i, j + "");
}
}
}
}
}
public static Set checkAllColumnPreerValues(int index, String sudoku) {
Set<String> values = new HashSet<>();
//here we get the column index, which in turn later enables us easier search
int columnIndex = index % 9;
for (int i = 0; i < sudoku.length(); i += 9) {
if (sudoku.substring(columnIndex + i, columnIndex + i + 1).matches("[1-9]")) {
values.add(sudoku.substring(columnIndex + i, columnIndex + i + 1));
}
}
return values;
}
public static Set checkAllRowPeerValues(int index, String sudoku) {
int rowIndex = index / 9;
Set<String> values = new HashSet<>();
for (int i = 0; i < 9; i++) {
int look = (rowIndex * 9) + i;
if (sudoku.substring(look, look + 1).matches("[1-9]")) {
values.add(sudoku.substring(look, look + 1));
}
}
return values;
}
public static Set checkAllBoxPeerValues(int index, String sudoku) {
int column = index % 9;
int row = index / 9;
int reducedCol = column / 3;
int reducedRow = row / 3;
int boxNumber = reducedCol + 3 * reducedRow;
Set<String> values = new HashSet<>();
return null;
}
//this method allows us to lookup which columns are covered by the row
public static HashMap<String, ArrayList<Integer>> matrixToRowValuesDict(ArrayList<int[]> matrix) {
String rowName = "row ";
HashMap<String, ArrayList<Integer>> row = new HashMap<String, ArrayList<Integer>>();
ArrayList<Integer> values = new ArrayList<Integer>();
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix.get(i).length; j++) {
if (matrix.get(i)[j] == 1) {
values.add(j);
}
}
row.put(rowName + i, values);
values = new ArrayList<Integer>();
}
return row;
}
//this method allows us to lookup which rows fill the column
public static HashMap<Integer, ArrayList<String>> matrixToValueRowsDict(HashMap<String, ArrayList<Integer>> rowValuesMatrix) {
HashMap<Integer, ArrayList<String>> valueRowsDict = new HashMap<Integer, ArrayList<String>>();
for (String key : rowValuesMatrix.keySet()) {
//iterate over every element that is stored under "key"
for (int i = 0; i < rowValuesMatrix.get(key).size(); i++) {
//if a value is already a key in the transformed dictionary
int currentValue = rowValuesMatrix.get(key).get(i);
if (valueRowsDict.keySet().contains(currentValue)) {
//add it if it isnt added already
if (!valueRowsDict.get(currentValue).contains(key)) {
valueRowsDict.get(currentValue).add(key);
}
} else {
ArrayList<String> values = new ArrayList<String>();
values.add(key);
valueRowsDict.put(currentValue, values);
values = new ArrayList<String>();
}
}
}
return valueRowsDict;
}
// </editor-fold>
//algorithm X
public static ArrayList<String> solve(HashMap<String, ArrayList<Integer>> rowColumnMatrix, HashMap<Integer, ArrayList<String>> columnRowMatrix, ArrayList<String> solution) {
if (columnRowMatrix.isEmpty()) {
//finished
return solution;
} else {
//normal run
//select column with least ones.
int column = selectColumnWithLeastOnes(columnRowMatrix);
//select a row from that column
ArrayList<String> rowsOfSelectedColumn = columnRowMatrix.get(column);
String row = selectRandomRow(rowsOfSelectedColumn);
//include row in the solution
solution.add(row);
//reduce matrix size and check if it is still valid
select(rowColumnMatrix, columnRowMatrix, row);
//repeat recursively
return solve(rowColumnMatrix, columnRowMatrix, solution);
}
}
public static void select(HashMap<String, ArrayList<Integer>> rowColumnMatrix, HashMap<Integer, ArrayList<String>> columnRowMatrix, String selectedRow) {
//here we collect all the rows that we will remove
Set<String> encounters = new HashSet<>();
//deep copy
HashMap<Integer, ArrayList<String>> testCopy = new HashMap(columnRowMatrix);
for (Integer key : columnRowMatrix.keySet()) {
ArrayList<String> tmp = new ArrayList<String>();
for (String value : columnRowMatrix.get(key)) {
tmp.add(value);
}
testCopy.put(key, tmp);
}
backupMonster.put(selectedRow, testCopy);
//this will tell us which columns to remove
ArrayList<Integer> columnsToRemove = rowColumnMatrix.get(selectedRow);
//we fill the set with all the rows that we will have to remove from columns
for (Integer column : rowColumnMatrix.get(selectedRow)) {
for (String subRow : columnRowMatrix.get(column)) {
encounters.add(subRow);
}
}
//we then remove the row letters from column matrix
for (String encouter : encounters) {
ArrayList<Integer> columns = rowColumnMatrix.get(encouter);
//createbackup
for (Integer columnd : columns) {
columnRowMatrix.get(columnd).remove(encouter);
}
}
//finally, we remove the rows from the matrix as well.
for (Integer rowToRemove : columnsToRemove) {
columnRowMatrix.remove(rowToRemove);
}
//after the matrix has been reduced, we check if it's still valid, and if not we rebuild and rerun the solve() on repaired one.
if (!areColsValid(columnRowMatrix)) {
invalidRows.add(selectedRow);
solution.remove(selectedRow);
HashMap<Integer, ArrayList<String>> testRestore = backupMonster.get(selectedRow);
for (Integer key : testRestore.keySet()) {
ArrayList<String> tmp = new ArrayList<String>();
for (String value : testRestore.get(key)) {
tmp.add(value);
}
columnRowMatrix.put(key, tmp);
}
}
}
//this method checks if the columnsMatrix is still valid state (there should be NO keys with empty values - 1 key has to have AT LEAST 1 value)
public static boolean areColsValid(HashMap<Integer, ArrayList<String>> columnsMatrix) {
for (Integer key : columnsMatrix.keySet()) {
if (columnsMatrix.get(key).isEmpty()) {
return false;
}
}
return true;
}
public static Integer selectColumnWithLeastOnes(HashMap<Integer, ArrayList<String>> columnRowMatrix) {
int leastElements = Integer.MAX_VALUE;
ArrayList<Integer> possibleCandidates = new ArrayList<Integer>();
//first we figure out lowest 1 amount
for (Integer column : columnRowMatrix.keySet()) {
if (columnRowMatrix.get(column).size() < leastElements) {
leastElements = columnRowMatrix.get(column).size();
}
}
//we add the columns with that amount of ones
for (Integer column : columnRowMatrix.keySet()) {
int counter = 0;
if (columnRowMatrix.get(column).size() == leastElements) {
//we check if all the rows yield wrong result, then we dont include this column
for(String candidateRow : columnRowMatrix.get(column))
{
if (invalidRows.contains(candidateRow)) {
counter+=1;
}
if (counter==columnRowMatrix.get(column).size()) {
invalidColumns.add(column);
}
}
if (!invalidColumns.contains(column)) {
possibleCandidates.add(column);
}
}
}
//we randomly pick a column BUT take care not to pick the one that gives unsolveable case
//int random = new Random().nextInt(possibleCandidates.size());
int random = myFakeRandomGenerator.nextInt(possibleCandidates.size());
//we generate new random until we have a valid candidate
while (invalidColumns.contains(possibleCandidates.get(random))) {
//random = new Random().nextInt(possibleCandidates.size());
random = myFakeRandomGenerator.nextInt(possibleCandidates.size());
}
return possibleCandidates.get(random);
}
public static String selectRandomRow(ArrayList<String> rowsFromSelectedCol) {
//int random = new Random().nextInt(rowsFromSelectedCol.size());
int random = myFakeRandomGenerator.nextInt(rowsFromSelectedCol.size());
while (invalidRows.contains(rowsFromSelectedCol.get(random))) {
//random = new Random().nextInt(rowsFromSelectedCol.size());
random = myFakeRandomGenerator.nextInt(rowsFromSelectedCol.size());
}
return rowsFromSelectedCol.get(random);
}
//we identify column as invalid if all of it's rows are in the invalidRows arraylist
public static boolean isColumnValid(ArrayList<String> invalidRows, int column){
ArrayList<String> rowsToCheck = columnsMatrix.get(column);
int counter = rowsToCheck.size();
for(String entry : rowsToCheck){
if (invalidRows.contains(entry)) {
counter+=1;
}
}
if (counter == rowsToCheck.size()) {
return false;
}
return true;
}
}
I'm writing breadth first, depth first, and depth first recursive traversal for the following graph:
From what I understand, the traversal should be 0 1 3 6 4 5 2...but i'm only getting that for the depth first traversal, and for the dfs(recursive) and BFS, I'm getting 0 1 3 6 2 4 5. I don't know which one is right and what I need to do to fix the problem.
Class
public void depthFirst(int vFirst,int n, int[] isvisited)
{ //vFirst = 0, n = 6
int v,i;
// st is a stack
st.push(vFirst);
while(!st.isEmpty())
{
v = st.pop();
if(isvisited[v]==0)
{
System.out.print(v);
isvisited[v]=1;
}
for ( i = 0; i <= n; i++)
{
if((adjMatrix[v][i] == 1) && (isvisited[i] == 0))
{
st.push(v);
isvisited[i]=1;
System.out.print(" " + i);
v = i;
}
}
}
}
public void depthFirstRecursive(int w) {
int j; //w = 0;
visited[w] = 1;
if (w == 0) {
System.out.print(w + " ");
}
for (j = 0; j <= 6; j++) {
if ((adjMatrix[w][j] == 1) && (visited[j] == 0)) {
System.out.print(j + " ");
depthFirstRecursive(j);
}
}
}
public void breadthFirst(int first, int p) {
int e; // first = 0; p = 6
int[] nodeVisited = new int[7];
que.add(first);
while (!que.isEmpty()) {
e = que.remove();
if(nodeVisited[e]==0)
{
System.out.print(e);
nodeVisited[e]=1;
}
for (int i = 0; i <= p; i++)
{
if((adjMatrix[e][i] == 1) && (nodeVisited[i] == 0))
{
que.add(e);
nodeVisited[i]=1;
System.out.print(" " + i);
e = i;
}
}
}
}
public static void main(String[] args) {
// 1 2 3 4 5 6 7
int[][] adjMatrix = { {0, 1, 1, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 0},
{1, 0, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0 ,0},
{0, 0, 1, 1, 1, 0, 0} };
new myGraphs(adjMatrix);
}
About following snippet in BFS:
que.add(e);
nodeVisited[i]=1;
System.out.print(" " + i);
e = i;
They why do you change e and add e to queue? It seems incorrect to me.
Non Recursive BFS using Queue:
public int[] breadthFirstSearch(int[][] adjacencyMatrix, int start) {
int totalNumberOfvertices = adjacencyMatrix.length;
boolean[] visited = new boolean[totalNumberOfvertices];
Queue<Integer> queue = new LinkedList<>();
queue.add(start);
visited[start] = true;
List<Integer> list = new ArrayList<>();
while (!queue.isEmpty()) {
list.add(queue.peek());
int currentFirstElementInQueue = queue.poll();
for (int i = 0; i < adjacencyMatrix.length; i++) {
if ((adjacencyMatrix[currentFirstElementInQueue][i] == 1) && (!visited[i])) {
queue.add(i);
visited[i] = true;
}
}
}
int[] result = new int[list.size()];
int i = 0;
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
result[i++] = itr.next();
}
return result;
}
public void BFS(int start)
{
int v=a.length;//a[][] is adj matrix declared globally
boolean visited[]=new boolean[v];//indexing done from 1 to n
LinkedList<Integer> queue=new LinkedList<Integer>();
visited[start]=true;
queue.add(start);
while(queue.size()!=0)
{
int x=queue.remove();
System.out.print(x+" ");
for (int i=1; i < v; i++)
if((a[x][i] == 1) && (!visited[i]))
{
queue.add(i);
visited[i]=true;
}
}
}