I've a problem with an exercise. I need to find all the solutions for a given sudoku, using fork/join parallelism. I made an algorithm but it seems it doesn't work. It stops at some point and I can't figure it out why.
Here's the code:
private static int counter;
private Cella[][] sudoku;
private int i;
private int j;
private int theCounter = 0;
public SudokuMulti(Cella[][] sudoku) {
this.sudoku = sudoku;
}
public SudokuMulti(Cella[][] sudoku, int i, int j) {
this.sudoku = sudoku;
this.i = i;
this.j = j;
}
//DELETED
// Copy the sudoku matrix
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
System.arraycopy(sudoku[i], 0, toReturn[i], 0, 9);
}
return toReturn;
}
And the code for the object Cella:
public class Cella {
private int current;
public Cella() {
current = 0;
}
public Cella(int current) {
this.current = current;
}
//Getter and Setter
My idea is to give to each thread the faculty to solve its own sudoku, given the "legal values" of the candidate cell. I then collect all threads in an ArrayList and ask them to fork with the last for. Every thread should return an Integer (0 for no success, 1 for success) in order to count how many possible sudokus can be solved.
However, the algorithm only covers 1/3 of the sudoku: after a certain point, it stops filling the cells and it just returns without completing it.
Can someone suggest me where I'm doing mistake(s) ?
From what code you have posted, I cannot see any issue that explains your problem. However, you have not posted code that I can compile and execute myself (known as a Minimum Working or Verifiable Example, see Wikipedia and StackOverflow's guide on creating one), nor have you posted a stack trace or output for your application. This makes it difficult to help you solve your problem. If you can provide me with more, I am willing to continue helping you with your problem.
In the meantime, I tried to throw together a program that solves the same problem following your approach. It seems to work, though I have not thoroughly unit-tested it. Perhaps you can compare it to what you wrote and use the differences to discover the problem. You will need at least Java 7 to compile and run this code.
If this is for a homework assignment, I recommend checking with your professor or TA before looking at this listing.
public class Main {
public static void main( String[] args ) {
Sudoku puzzle = new Sudoku();
// Uncomment these lines to have a uniquely solvable Sudoku puzzle. They are commented out to prove that this code can count multiple solutions.
// puzzle.set(1, 0, 2);
// puzzle.set(2, 0, 9);
// puzzle.set(4, 0, 5);
// puzzle.set(7, 0, 4);
// puzzle.set(8, 0, 1);
// puzzle.set(3, 1, 8);
// puzzle.set(6, 1, 3);
// puzzle.set(2, 2, 3);
puzzle.set(3, 2, 7);
puzzle.set(4, 2, 4);
puzzle.set(5, 2, 9);
puzzle.set(6, 2, 6);
puzzle.set(3, 3, 4);
puzzle.set(6, 3, 2);
puzzle.set(7, 3, 1);
puzzle.set(1, 4, 6);
puzzle.set(3, 4, 3);
puzzle.set(4, 4, 7);
puzzle.set(5, 4, 1);
puzzle.set(7, 4, 8);
puzzle.set(1, 5, 4);
puzzle.set(2, 5, 1);
puzzle.set(5, 5, 6);
puzzle.set(2, 6, 5);
puzzle.set(3, 6, 9);
puzzle.set(4, 6, 2);
puzzle.set(5, 6, 8);
puzzle.set(6, 6, 7);
puzzle.set(2, 7, 4);
puzzle.set(5, 7, 7);
puzzle.set(0, 8, 3);
puzzle.set(1, 8, 7);
puzzle.set(4, 8, 6);
puzzle.set(6, 8, 5);
puzzle.set(7, 8, 2);
SudokuSolver solver = new SudokuSolver(puzzle);
long start = System.nanoTime();
int totalSolutions = solver.compute();
long end = System.nanoTime();
System.out.println(totalSolutions);
System.out.format("%f ms", (end - start) / 1e6);
}
private static class Sudoku {
private final int[][] cells;
Sudoku() {
cells = new int[9][9];
}
Sudoku( Sudoku original ) {
cells = new int[9][9];
for (int column = 0; column < 9; ++column) {
for (int row = 0; row < 9; ++row) {
set(column, row, original.get(column, row));
}
}
}
int get( int column, int row) {
return cells[column][row];
}
void set( int column, int row, int value ) {
cells[column][row] = value;
}
boolean isPlausible() {
return columnsArePlausible() && rowsArePlausible() && blocksArePlausible();
}
private boolean columnsArePlausible() {
boolean result = true;
for (int column = 0; result && column < 9; ++column) {
result = isColumnPlausible(column);
}
return result;
}
private boolean isColumnPlausible( int column ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int row = 0; result && row < 9; ++row) {
int value = get(column, row);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
return result;
}
private boolean rowsArePlausible() {
boolean result = true;
for (int row = 0; result && row < 9; ++row) {
result = isRowPlausible(row);
}
return result;
}
private boolean isRowPlausible( int row ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int column = 0; result && column < 9; ++column) {
int value = get(column, row);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
return result;
}
private boolean blocksArePlausible() {
boolean result = true;
for (int column = 0; result && column < 9; column += 3) {
for (int row = 0; result && row < 9; row += 3) {
result = isBlockPlausible(column, row);
}
}
return result;
}
private boolean isBlockPlausible( int column, int row ) {
boolean result = true;
boolean[] seen = new boolean[10];
for (int x = 0; result && x < 3; ++x) {
for (int y = 0; result && y < 3; ++y) {
int value = get(column + x, row + y);
if (value > 0 && seen[value]) {
result = false;
} else {
seen[value] = true;
}
}
}
return result;
}
}
private static class SudokuSolver extends RecursiveTask<Integer> {
private static final long serialVersionUID = 8759452522630056046L;
private Sudoku state;
private int column;
private int row;
SudokuSolver( Sudoku state ) {
this.state = state;
// These settings allow the search loop in compute() to increment first without asking questions about
// whether this cell has been checked yet.
column = -1;
row = 8;
}
SudokuSolver( Sudoku state, int column, int row ) {
this.column = column;
this.row = row;
this.state = state;
}
#Override
protected Integer compute() {
int viableSolutions = 0;
if (state.isPlausible()) {
int originalColumn = column;
int originalRow = row;
do {
if (row + 1 >= 9) {
++column;
row = 0;
} else {
++row;
}
} while (column < 9 && state.get(column, row) != 0);
if (column >= 9) {
viableSolutions = 1;
} else {
List<SudokuSolver> solvers = new ArrayList<>();
for (int value = 1; value <= 9; ++value) {
Sudoku copy = new Sudoku(state);
copy.set(column, row, value);
solvers.add(new SudokuSolver(copy, column, row));
}
invokeAll(solvers);
for (SudokuSolver solver : solvers) {
viableSolutions += solver.join();
}
}
}
return viableSolutions;
}
}
}
Since this code times how long it takes to count the solutions, the output can vary, but I got
354
709.848410 ms
I've found a solution. Here is the error:
// Copy the sudoku matrix
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
// !!ERROR!!
System.arraycopy(sudoku[i], 0, toReturn[i], 0, 9);
}
return toReturn;
}
When I copy the array I fill it with the Cella object reference and not with a new one, so it causes data races.
The correct way to copy the matrix is:
private Cella[][] createCopy() {
Cella[][] toReturn = new Cella[9][9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
toReturn[i][j] = new Cella(sudoku[i][j].getCurrent());
}
}
return toReturn;
}
Related
I have an assignment in which I have to create the following classes:
public class Square3x3 {
private int[][] mat = new int [3][3];
public boolean allThere(){
int[] options = {1,2,3,4,5,6,7,8,9};
for (int i = 0 ; i < NUM_OF_ROWS; i++){
for(int j =0 ; j < NUM_OF_COLS; j++){
for (int k = 0; k < options.length; k++){
if(mat[i][j] == options[k]) {
options[k] = -1;
break;
}
}
}
}
for (int num : options) {
if(num != -1) return false;
}
return true;
}
a class that represents a 3x3 2d array, and a sudoku class that is constructed by a 3x3 2d array of Square3x3 objects:
public class Sudoku {
private Square3x3[][] grid9x9 = new Square3x3[3][3];
}
I need to check if the 9x9 grid is valid, I have a method to check if a single 3x3 object is valid, but I also need to check if the entire row/col of the 9x9 grid is valid (has all the numbers from 1-9)
Here's one way to improve your data definitions using the same two classes. Define one 9 x 9 int array, and pass a sub-array to your allThere method by using the row and column indexes.
public class Sudoku {
private int[][] grid9x9 = new int[9][9];
}
public class Square3x3 {
public boolean allThere(int[][] grid, int row, int column) {
int[] options = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
for (int i = row; i < row + 3; i++) {
for (int j = column; j < column + 3; j++) {
options = testOptions(options, grid[i][j]);
}
}
for (int num : options) {
if (num != -1)
return false;
}
return true;
}
private int[] testOptions(int[] options, int gridValue) {
for (int i = 0; i < options.length; i++) {
if (gridValue == options[i]) {
options[i] = -1;
break;
}
}
return options;
}
}
I cleaned up your allThere code to document that the break statement only breaks out of the options loop.
I have an assignment to implementthe matrix class and a method that checks if the matrix is symmetric.
The method has to be recursive and then I have to calculate its complexity. After I have to transform the recursive function to its iterative version.
For now this is how my matrix class looks like:
public class Matrix<T> {
private int m, n;
private T[][] data;
public Matrix(int m, int n) {
this.m = m;
this.n = n;
}
public Matrix(T[][] data) {
this.data = data;
}
public boolean isSymmetric() {
if (m != n) {
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (data[i][j] != data[j][i]) {
return false;
}
}
}
return true;
}
return false;
}
public boolean isSymmetric(int i, int j) {
if (i < 0 && j < 0) return true;
else {
return isSymmetric(i - 1, j - 1);
}
}
public T get(int i, int j) {
return data[i][j];
}
public void set(int i, int j, T value) {
data[i][j] = value;
}
public int[] getSize() {
return new int[]{m, n};
}
#Override
public String toString() {
String rep = "";
for (int i = 0; i < m; i++) {
rep += "( ";
for (int j = 0; j < n; j++) {
rep += data[i][j].toString() + "\t";
}
rep += ")\n";
}
return rep;
}
}
I have a iterative version of the isSymmetric() function, but I cannot get the recursive one.
You can start check from maximum row and col each recursion will be decrese it by 1 until 0;
public class Matrix<T> {
private final int height;
private final int width;
private final T[][] data;
public Matrix(T[][] data) {
height = data.length;
width = data[0].length;
this.data = data; // it brakes OOP: encapsulation
}
public boolean isSymmetricIterative() {
if (height != width)
return false;
for (int row = 0; row < height; row++)
for (int col = 0; col < width; col++)
if (data[row][col] != data[col][row])
return false;
return true;
}
public boolean isSymmetricRecursive() {
return isSymmetricRecursive(height - 1, width - 1);
}
private boolean isSymmetricRecursive(int row, int col) {
return row < 0 && col < 0 || data[row][col] == data[col][row] && isSymmetricRecursive(row - 1, col - 1);
}
}
In the recursive version, you forgot to add a check to see if the two elements are equal. Without it, there is no case where the method would return false.
public boolean isSymmetric() {
return m == n && isSymmetric(m - 1, n - 1);
}
public boolean isSymmetric(int i, int j) {
if (i < 0 && j < 0) return true;
else if (data[i][j] != data[j][i]) return false;
else {
return isSymmetric(i - 1, j - 1);
}
}
Symmetric matrix is a square matrix that is equal to its transpose. Let's assume that we have a square matrix.
To avoid unnecessary iterations and to reduce the time complexity, you can iterate over the indices only in the lower left corner of the matrix and compare the corresponding elements with those in the upper right corner m[i][j]==m[j][i], excluding the main diagonal, until the first mismatch.
Try it online!
// let's assume that we have a square matrix
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3, 4, 5},
{2, 3, 4, 5, 6},
{3, 4, 5, 6, 7},
{4, 5, 6, 7, 8},
{5, 6, 7, 8, 9}};
System.out.println(isSymmetric(matrix)); // true
System.out.println(isSymmetricR(matrix, 1, 0)); // true
}
// iterative version
static boolean isSymmetric(int[][] matrix) {
return IntStream.range(1, matrix.length)
.allMatch(i -> IntStream.range(0, i)
//intermediate output
.peek(j -> System.out.println("i=" + i + ",j=" + j))
.allMatch(j -> matrix[i][j] == matrix[j][i]));
}
// recursive version
static boolean isSymmetricR(int[][] matrix, int i, int j) {
if (i < matrix.length && j < i) {
//intermediate output
System.out.println("i=" + i + ",j=" + j);
if (matrix[i][j] == matrix[j][i]) {
if (j == i - 1) {
return isSymmetricR(matrix, i + 1, 0);
} else {
return isSymmetricR(matrix, i, j + 1);
}
} else {
// the first mismatch, the
// matrix is not symmetric
return false;
}
} else {
// if reached this point,
// the matrix is symmetric
return true;
}
}
The intermediate output is the same in both cases:
i=1,j=0
i=2,j=0
i=2,j=1
i=3,j=0
i=3,j=1
i=3,j=2
i=4,j=0
i=4,j=1
i=4,j=2
i=4,j=3
See also: How to remove rows and columns containing only zeros from a 2d matrix?
I am having trouble to create a (recursive) function that prints all possible indexes for a multi dimensional table.
I got the information about the multi-dimensionality as an array.
Example:
int[]{6,6} would be a 2-dimensional table with 6x6 = 36 fields, so the result would be [0,0],[0,1],[1,1],[1,2],[2,2]... and so on.
Another example:
int[]{2,2,2} would be a 3-dimensional table with 8 possible indexes: [0,0,0],[0,0,1],[0,1,1]... and so on
I'm trying to do this in Java 7.
Edit: As requested, what I got so far. Code is producing OutOfBound Exception.
loop(new int[2], new int[]{6, 6}, 0);
private void loop(int[] index, int[] dimensionSizes, int dimensionIndex) {
if (index[dimensionIndex] < dimensionSizes[dimensionIndex] && dimensionIndex < dimensionSizes.length) {
System.out.println(Arrays.toString(index));
index[dimensionIndex] = index[dimensionIndex] + 1;
if (index[dimensionIndex] < dimensionSizes[dimensionIndex]) {
loop(index, dimensionSizes, dimensionIndex);
} else {
loop(index, dimensionSizes, dimensionIndex + 1);
}
}
}
I think this code could respond to your question:
public static void printAllIndex(int[] dimensions) {
int[] index = new int[dimensions.length];
int stepNumber = 0;
// Initialization
for (int i : index) { index[i] = 0; } // init index to 0
for (int d : dimensions) { stepNumber += d; } // count number of iteration needed
System.out.println(Arrays.toString(index)); // print first index [0,0,...]
for(int s = 0; s <= stepNumber - 1; s++) {
boolean allEquals = true;
int value = index[index.length - 1];
for (int i = index.length - 1; i >= 0; i--) {
if(index[i] != value) {
index[i]++;
allEquals = false;
break;
}
}
if (allEquals) { index[index.length - 1]++; }
System.out.println(Arrays.toString(index));
}
}
I have this Knight's Tour code but am getting a java.lang.StackOverflowError on line 37. I'm not really sure where to go from here to fix it. I think the code in my main has something to do with it but I'm not sure what to do with it at this point. Any help is greatly appreciated thanks.
public class Main {
public static void main(String[] args) {
Main tour = new Main();
tour.solveKnightTour();
}
private static int chessboard[][];
boolean a = true;
public Main() {
chessboard = new int[8][8];
}
private void matrixChessBoard() {
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
System.out.printf("%5d", chessboard[i][j]);
}
System.out.println();
}
}
static boolean tour(int advance, int horizontal, int vertical, int xMove[], int yMove[]) {
int i = 0;
int moveHoriz = 0;
int moveVert = 0;
boolean a = true;
chessboard[horizontal][vertical] = advance;
if (advance == 63) {
for (int t = 0; t < 8; t++) {
for (int u = 0; u < 8; u++) {
System.out.printf("%5d", chessboard[t][u]);
}
System.out.println("\n");
}
} else {
for (int j = 0; j < 8; j++) {
if ((horizontal + xMove[j] < 8 & (vertical + yMove[j]) >= 0 & (vertical + yMove[i]) < 8)
& (horizontal + xMove[i]) >= 0){
if (chessboard[horizontal + xMove[i]][vertical + yMove[i]] == -1){
//line 37 if (tour(moveHoriz, moveVert, advance + 1, xMove, yMove)){
break;
}
}
}
}
a = false;
chessboard[horizontal][vertical] = -1;
}
return a;
}
public boolean solveKnightTour() {
for (int x = 0; x < 8; x++) {
for (int y = 0; y < 8; y++) {
chessboard[x][y] = -1;
}
}
int xMove[] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int yMove[] = { 1, 2, 2, 1, -1, -2, -2, -1 };
chessboard[0][0] = 0;
if (!tour(0, 0, 1, xMove, yMove)) {
return false;
} else {
matrixChessBoard();
}
return true;
}
}
Consider a stripped down version of your tour() method:
static boolean tour(int advance, int horizontal, int vertical, ...) {
int moveHoriz = 0;
int moveVert = 0;
if (false) {
...
} else {
if (true)
tour(moveHoriz, moveVert, advance + 1, ...);
}
}
Called with tour(0, 0, 1, ...), the function will enter with advance=0. Various assignments will be done, various tests will be made, and then the tour(moveHoriz, moveVert, advance+1, ...) statement will be executed, which evaluates to the call tour(0, 0, 1, ...). Repeat until stack overflow.
moveHoriz is passed to the advance parameter
moveVert is passed to the horizontal parameter
advance+1 is passed to the vertical parameter
This is clearly not what you intended. Since advance+1 is not passed to advance, the if (advance == 63) condition will always evaluate to false, and you never break out of the recursion.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have following homework to do:
Implement parallel searching for specified element in array. Use number of threads as a function parameter. Eeach thread checks own array piece size of (ArraySize/NumberOfThreads).
class MyThread extends Thread {
final int[] SEARCH_TAB;
final int RANGE_TAB[][];
final int SEARCH_VALUE;
static int searchIndex = -1;
static boolean isWorking = true;
int whichThread;
MyThread(int[] searchTab, int[][] rangeTab, int searchValue, int whichThread) {
SEARCH_TAB = searchTab;
RANGE_TAB = rangeTab;
SEARCH_VALUE = searchValue;
this.whichThread = whichThread;
}
#Override
public void run() {
for (int i = RANGE_TAB[whichThread][0]; i < RANGE_TAB[whichThread][1] && isWorking; ++i) {
synchronized(this) {
if (SEARCH_TAB[i] == SEARCH_VALUE) {
isWorking = false;
searchIndex = i;
}
}
}
}
}
class Main {
private static int[][] range(int n, int p) {
int[] quantities = new int[p];
int remainder = n % p;
int quotient = n/p;
int i;
for (i = 0; i < p; ++i) quantities[i] = quotient;
i = 0;
while (remainder != 0) {
--remainder;
++quantities[i];
++i;
}
int[][] tab = new int[p][2];
tab[0][0] = 0;
tab[0][1] = quantities[0];
for (i = 1; i < p; ++i) {
tab[i][0] = tab[i-1][1];
tab[i][1] = tab[i][0] + quantities[i];
}
return tab;
}
private static int search(int[] searchTab, int numberOfThreads, int searchValue) {
int[][] rangeTab = range(searchTab.length, numberOfThreads);
Thread[] threads = new Thread[numberOfThreads];
for ( int i = 0; i < numberOfThreads; ++i) threads[i] = new MyThread(searchTab, rangeTab, searchValue, i);
for ( int i = 0; i < numberOfThreads; ++i) threads[i].start();
return MyThread.searchIndex;
}
public static void main(String[] args) {
int[] tab = {0, 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10};
int value = 5;
int valueIndex = search(tab, 1, value);
if (valueIndex == -1) System.out.println("Not found.");
else System.out.println(valueIndex);
}
}
This code generally works but cant't find index when one thread is implemented. By the way my teacher said that my code is too long and complicated any suggestions with that?
I will be grateful for any kind of help.
How about the following code:
public class Searcher implements Runnable {
private int intToFind;
private int startIndex;
private int endIndex;
private int[] arrayToSearchIn;
public Searcher(int x, int s, int e, int[] a) {
intToFind = x;
startIndex = s;
endIndex = e;
arrayToSearchIn = a;
}
public void run() {
for (int i = startIndex; i <= endIndex; i++) {
if (arrayToSearchIn[i] == intToFind) System.out.println("Found x at index: " + i);
}
}
}
public class Starter {
public static void main(String[] args) {
int[] a = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int numberOfThreads = 5;
int x = 20;
findElement(numberOfThreads, x, a);
}
private static void findElement(int numberOfThreads, int x, int[] a) {
int sizeOfa = a.length;
int range = sizeOfa/numberOfThreads;
for (int i = 0; i <= numberOfThreads-1; i++) {
Thread searcher;
if (i == numberOfThreads-1) {
searcher = new Thread(new Searcher(x, i*range, sizeOfa-1, a));
} else {
searcher = new Thread(new Searcher(x, i*range, i*range+range-1, a));
}
searcher.start();
}
}
}
You can still optimize the code e.g. by splitting the rest of the array on all threads instead of just pushing it into the last one (like in my code) but the idea is still the same.
EDIT: I think that there is a problem with your code. It will only show one appearance of x in the array. If you are looking for x = 5 in [5,5,5,5,5] using five threads you can neven know which index will be returned because it depends on how your threads are scheduled. The outcome will be between 0 and 5.