So I have a sudoku algorithm for a generating a completed game board. The problem is that the algorithm in some instances runs out of possible values to place in the grid, so by default it places a 0.
Here's the code:
public void generateBoard() {
// Determine values for board
int r, d;
// For every slot in grid
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
// Create HashSet with values 1-9
for (int k = 1; k <= 9; k++) {
set.add(k);
}
checkRow(i);
checkCol(j);
checkBox(i, j);
// Create an iterator
Iterator<Integer> iterator = set.iterator();
// Add HashSet values to ArrayList via Iterator
while (iterator.hasNext()) {
d = iterator.next();
values.add(d);
}
try {
// Randomly choose from list of viable values to be put into slot
r = new Random().nextInt(values.size());
slots[i][j] = (Integer) values.get(r);
} catch (Exception e) {
e.printStackTrace();
//resetBoard();
//continue;
}
// Clear HashSet and ArrayList after slot is assigned value
values.clear();
set.clear();
}
}
}
public void checkRow(int i) {
for (int c = 1; c <= 9; c++) {
for (int a = 0; a < 9; a++) {
// If c value is already in row remove from HashSet
if (c == slots[i][a]) {
set.remove(c);
}
}
}
}
public void checkCol(int j) {
for (int c = 1; c <= 9; c++) {
for (int a = 0; a < 9; a++) {
// If c value is already in column remove from HashSet
if (c == slots[a][j]) {
set.remove(c);
}
}
}
}
public void checkBox(int i, int j) {
int xSet = (i - (i % 3));
int ySet = (j - (j % 3));
for (int c = 1; c <= 9; c++) {
for (int x = xSet; x < xSet + 3; x++) {
for (int y = ySet; y < ySet + 3; y++) {
// If c value is already in box remove from HashSet
if (c == slots[x][y]) {
set.remove(c);
}
}
}
}
}
And this is what the generated board looks like: http://imgur.com/2cWh61j
The reason why your algorithm fails is because it's inherently wrong. Generating a Sudoku puzzle is more complicated than that.
A shortcut sometimes used to create a puzzle is to hardcode a few correct puzzles, picking one at random, shuffling the digits (swap all Xs with Ys and vice versa, and so on) shuffling the rows/columns (without moving any number outside its old box) and shuffling the 3x9 and 9x3 areas along the box borders. Doing so will create a puzzle that's TECHNICALLY the same as the original from a mathematical standpoint but should "feel" unique enough to a human.
Also keep in mind that even when you have a complete board, figuring out which tiles you can safely remove without creating an ambiguous puzzle is a bit tricky as well. The naive "remove x tiles at random" solution often fails.
Another question (with some useful answers) about how to create Sudokus can be found here: How to generate Sudoku boards with unique solutions
Related
I'm trying to implement insertion sort and it works for one weird implementation but in reverse order. The same goes for another selection sort I was trying but it working the same way.
void insertionSort(ArrayList<T> genericAList) {
for (int n = 1; n < genericAList.size(); n++) {// go from start to end
// n=genericList.size
//n is primary index, j is secondary ind
for (int j = 0; j < n; j++) { // This sorts in descending order
//WHY DOES THIS NOT WORK?? for (int j = n-1; j>0; j--) {
if (genericAList.get(n).compareTo(genericAList.get(j)) == 1) {
T ncopy = genericAList.get(n);
genericAList.set(n, genericAList.get(j));
genericAList.set(j, ncopy);
}
}
//unsuccessfully trying to copy the array to reverse the order
ArrayList<T> copy = new ArrayList<>();
for (int i = genericAList.size() - 1; i >= 0; i--) { // start from end of old
copy.add(genericAList.get(i));
}
// genericAList=copy;
}
// return clone();
}
Note that compareTo is not guaranteed to return -1 or 1 for larger or smaller.
It returns 0 if they are the same, and then a number larger or smaller than 0 if they are different.
Imagine the pseudo-code for a primitive form of this - if we're comparing two numbers for instance we might do this:
public int compareTwoNumbers(x, y) {
return x - y;
}
So comparing 5 and 3 will give you -2 or 2 (for instance, depending on which way around they are).
The for loop should be int j = n; j > 0; j--, the == 1 should be > 0, and you're comparing/swapping the element at n when it should be j - 1.
public static int[][] solve(int[][] input){
for (int i = 0; i < 9*9; i++){
if(input[i / 9][i % 9] != 0){
continue;
}
for (int j = 1; j <= 9; j++){
if(validNumber(input, i / 9, i % 9, j)){
input[i / 9][i % 9] = j;
solve(input);
}
}
}
return input;
}
This method should solve a (solvable) sudoku puzzle via backtracking regardless of the initial situation. It works like this:
Given a sudoku puzzle it iterates from the upper left corner over each row to the lower right corner of the 2D array. When there is already a number, it gets skipped. When there is a zero (empty field) it calculates possible values via the validNumber method. The first valid number (from 1 to 9) is put in the field and the method goes to the next field.
In this algorithm the method does not now whether or not a valid number will eventually render the puzzle unsolvable.
I want to alter it like this:
At the end, when the method finishes iterating through the whole 2d array, every entry of the array gets tested if it is a zero or not.
If there is even one zero the whole algorithm must go to the place where the very first "valid" number was put in. Now, the next "valid" number is put in and so on until there are no zeroes at the end of the algorithm.
I have some troubles implementing this thought. It seems to me there must be an other for loop somewhere, or something like a goto statement, but I don't know where to put it.
Any advice?
I implemented a Sudoku solver once before. It was a bit more complicated than what you had, but solved the game in a blink. :)
What you are attempting to do is solve Sudoku by "Brute Force" and using (tail) recursion. That means you are attempting to solve the board by iterating over all 981 possible combinations. 9 to the power of 81 is... well it's a big number. And so your approach will take eternity, but you'll run out of stack space from the tail recursion much sooner.
When I implemented Sudoko, it was more straight up. It kept a 9x9 array of "items", where each item was the value in the square, and an array of 9 booleans representing candidates (true == viable, false == eliminated). And then it just did a non-recursive loop of solving the board.
The main loop would start with the simple process of finding squares with only 1 remaining candidate. Then the next step would do simple candidate elimination based on values already assigned. Then it would work its way into more complicated elimination techniques such as X-Wing.
Your algorithm does not actually backtrack. It moves forward if it can, but it never moves backwards when it realizes it's stuck in a corner. This is because it never returns any knowledge up the stack, and it never resets squares. Unless you get really lucky, your code will get the game board into a cornered state, and then print out that cornered state. To backtrack, you need to reset the last square you set (the one that got you cornered) to zero, so your algorithm will know to keep trying other things.
For understanding backtracking, I highly recommend a book called The Algorithm Design Manual by Steven Skiena. I read it when I was preparing for SWE interviews, and it really improved my knowledge of backtracking, complexity, and graph search. The second half of the book is a catalog of 75 classic algorithmic problems, and Sudoku is one of them! He has an interesting analysis of optimizations you can make to prune the search tree and solve very hard puzzle boards. Below is some code I wrote a long time ago after reading this chapter (probably not that high quality by my current standards, but it works). I just read through it really quickly and added the solveSmart boolean in the solve method which allows you to turn one of those optimizations on or off, which results in a pretty big time savings when solving a "hard" class Sudoku board (one with only 17 squares filled in to start with).
public class Sudoku {
static class RowCol {
int row;
int col;
RowCol(int r, int c) {
row = r;
col = c;
}
}
static int numSquaresFilled;
static int[][] board = new int[9][9];
static void printBoard() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
System.out.print(" " + (board[i][j] == 0 ? " " : board[i][j]) + " ");
if (j % 3 == 2 && j < 8)
System.out.print("|");
}
System.out.println();
if (i % 3 == 2 && i < 8)
System.out.println("---------|---------|---------");
}
System.out.println();
}
static boolean isEntireBoardValid() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (!isBoardValid(i, j)) {
return false;
}
}
}
return true;
}
static boolean isRowValid(int row) {
int[] count = new int[9];
for (int col = 0; col < 9; col++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isColValid(int col) {
int[] count = new int[9];
for (int row = 0; row < 9; row++) {
int n = board[row][col] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
return true;
}
static boolean isSquareValid(int row, int col) {
int r = (row / 3) * 3;
int c = (col / 3) * 3;
int[] count = new int[9];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int n = board[r + i][c + j] - 1;
if (n == -1)
continue;
count[n]++;
if (count[n] > 1)
return false;
}
}
return true;
}
static boolean isBoardValid(int row, int col) {
return (isRowValid(row) && isColValid(col) && isSquareValid(row, col));
}
static RowCol getOpenSpaceFirstFound() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
return new RowCol(i, j);
}
}
}
return new RowCol(0, 0);
}
static RowCol getOpenSpaceMostConstrained() {
int r = 0, c = 0, max = 0;
int[] rowCounts = new int[9];
int[] colCounts = new int[9];
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] != 0)
rowCounts[i]++;
if (board[j][i] != 0)
colCounts[i]++;
}
}
int[][] squareCounts = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
int count = 0;
for (int m = 0; m < 3; m++) {
for (int n = 0; n < 3; n++) {
if (board[(i * 3) + m][(j * 3) + n] != 0)
count++;
}
}
squareCounts[i][j] = count;
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (board[i][j] == 0) {
if (rowCounts[i] > max) {
max = rowCounts[i];
r = i;
c = j;
}
if (colCounts[j] > max) {
max = rowCounts[j];
r = i;
c = j;
}
}
}
}
return new RowCol(r, c);
}
static boolean solve() {
if (81 == numSquaresFilled) {
return true;
}
boolean solveSmart = true;
RowCol rc = solveSmart ? getOpenSpaceMostConstrained() : getOpenSpaceFirstFound();
int r = rc.row;
int c = rc.col;
for (int i = 1; i <= 9; i++) {
numSquaresFilled++;
board[r][c] = i;
if (isBoardValid(r, c)) {
if (solve()) {
return true;
}
}
board[r][c] = 0;
numSquaresFilled--;
}
return false;
}
public static void main(String[] args) {
// initialize board to a HARD puzzle
board[0][7] = 1;
board[0][8] = 2;
board[1][4] = 3;
board[1][5] = 5;
board[2][3] = 6;
board[2][7] = 7;
board[3][0] = 7;
board[3][6] = 3;
board[4][3] = 4;
board[4][6] = 8;
board[5][0] = 1;
board[6][3] = 1;
board[6][4] = 2;
board[7][1] = 8;
board[7][7] = 4;
board[8][1] = 5;
board[8][6] = 6;
numSquaresFilled = 17;
printBoard();
long start = System.currentTimeMillis();
solve();
long end = System.currentTimeMillis();
System.out.println("Solving took " + (end - start) + "ms.\n");
printBoard();
}
}
Eventually validNumber() method will not return any number because there is no possibilities left that means one of the previous choices was incorrect. Just imagine that the algorithm is started with the empty grid (obviously this puzzle is solvable1).
The solution is to keep tree of possible choices and if some choices are incorrect, then just remove them from the tree and use the next available choice (or step back on a higher level of the tree, if there is no choice left in this branch). This method should find a solution if any. (Actually this is how I implemented my sudoku solver some time ago.)
1 IMHO there are 3 different kinds of sudoku:
"true" correct sudoku that has a single unique complete solution;
ambiguous sudoku that has multiple distinct complete solutions, e.g. a puzzle with only 7 different numbers, so it has at least two distinct solutions that differ by swapping 8th and 9th numbers;
incorrect sudoku that has no complete solution, e.g. with a row with two or more occurrences of the same number.
With this definition, a solver algorithm should either:
prove that there is no solution;
return complete solution that satisfies the initial grid.
In the case of a "true" sudoku the result is a "true" solution by definition. In the case of an ambiguous sudoku the result can be different depending on the algorithm. An empty grid is the ultimate example of ambiguous sudoku.
so im taking an ap comp sci class in school, and in the class we're learning about the basics of java. For this assignment we have to make permutations by taking numbers from one one-dimensional array, and putting in another, then deleting that number so it can't be picked again. The numbers in the array can't repeat. We have to use the ArrayList Class too. And I can't figure out what's wrong!
This is the method that creates the permutations:
public static ArrayList<Integer> createPerm()
{
ArrayList<Integer> list = new ArrayList<Integer>(10);
Integer x = 1, remove = 0;
for (Integer i = 0; i < 10; i++)
{
list.add(x);
x++;
}
ArrayList<Integer> perm = new ArrayList<Integer>(10);
for(Integer i = 0; i < 10; i++)
{
Integer r = (int)(Math.random() * 10) + 1;
for (Integer j = 0; j <= list.size() - 1; j++)
{
if (list.get(j) == r)
{
remove = j + 1;
list.remove(remove);
perm.add(r);
}
}
}
return perm;
}
I think that you (and I also:)) got a lttle bit confused because you are using Integer-objects as index and as list elements.
That is no problem with the List.get method, because there is only one get method which is expecting an int and Java converts the Integer to int.
The problem is in your usage of list.remove(). There are two methods, one expects an object and one an int.
So if you pass an Integer object, the remove(Object) method is called. But you pass the index, not the r-matching object, so the remove method fails sometimes, because it is random if the element is in your list if remove was called before. And if the method not fails, you have removed the element with the value of your index(+1), not the one who matches r.
for(Integer i = 0; i < 10; i++)
{
Integer r = (int)(Math.random() * 10) + 1;
for (Integer j = 0; j <= list.size() - 1; j++)
{
if (list.get(j) == r)
{
remove = j + 1;
list.remove(remove);//the main error is here you found 4
//on index 2 and removes 3 (because of +1)
perm.add(r);
}
}
}
The next thing is, that random can deliver the same number more than once,
so you should not loop only 10 times. Loop until the list is empty.
I have corrected the code as below, the original lines are commented before the correction.
//for (Integer i = 0; i < 10; i++) {
while (!list.isEmpty()) {
Integer r = (int) (Math.random() * 10) + 1;
for (Integer j = 0; j <= list.size() - 1; j++) {
//if (list.get(j) == r) {
if (list.get(j).equals(r)) {
//remove = j + 1;
remove = list.get(j);
list.remove(remove);
perm.add(r);
}
}
}
And here I put the code somewhat more clearly, so that it is easier to read
public static ArrayList<Integer> createPerm() {
ArrayList<Integer> list = new ArrayList<Integer>(10);
for (int i = 0; i < 10; i++) {
list.add(i+1);
}
ArrayList<Integer> perm = new ArrayList<Integer>(10);
while (!list.isEmpty()) {
int r = (int) (Math.random() * 10) + 1;
for (int j = 0; j < list.size(); j++) {
if (list.get(j).intValue() == r) {
perm.add(list.remove(j));
}
}
}
return perm;
}
I am having a really hard time creating a method to raise a matrix to the power. I tried using this
public static int powerMethod(int matrix, int power) {
int temp = matrix ;
for (int i = power; i == 1; i--)
temp = temp * matrix ;
return temp ;
but the return is WAYYY off. Only the first (1,1) matrix element is on point.
I tried using that method in a main like so
// Multiplying matrices
for (i = 0; i < row; i++)
{
for (j = 0; j < column; j++)
{
for (l = 0; l < row; l++)
{
sum += matrix[i][l] * matrix[l][j] ;
}
matrix[i][j] = sum ;
sum = 0 ;
}
}
// Solving Power of matrix
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++)
matrixFinal[power][i][j] = Tools.powerMethod(matrix[i][j], power) ;
}
Where "power", "row", and "column" is an int that the user enters.
Any ideas how I can do this??
Thanks!!!
You have a lot of issues here.
First, your matrix squaring algorithm has a (common) error. You have:
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++) {
for (l = 0; l < row; l++) {
sum += matrix[i][l] * matrix[l][j] ;
}
matrix[i][j] = sum ;
sum = 0 ;
}
}
However, you need to store the result in a temporary second matrix, because when you do matrix[i][j] = sum, it replaces the value at that position with the output, then later results end up being incorrect. Also I suggest initializing sum to 0 first, since it appears you declare it outside of this loop, and initializing it first protects you against any arbitrary value sum may have before going into the loop. Furthermore, it is not immediately clear what you mean by row and column -- make sure you are iterating over the entire matrix. E.g.:
int temp[][] = new int[matrix.length];
for (i = 0; i < matrix.length; i++) {
temp[i] = new int[matrix[i].length];
for (j = 0; j < matrix[i].length; j++) {
sum = 0 ;
for (l = 0; l < matrix.length; l++) {
sum += matrix[i][l] * matrix[l][j] ;
}
temp[i][j] = sum ;
}
}
// the result is now in 'temp', you could do this if you wanted:
matrix = temp;
Note that matrix.length and matrix[i].length are fairly interchangeable above if the matrix is square (which it must be, in order to be multiplied by itself).
Secondly, your multiplication squares a matrix. This means if you repeatedly apply it, you keep squaring the matrix every time, which means you will only be able to compute powers that are themselves powers of two.
Your third issue is your final bit doesn't make much sense:
for (i = 0; i < row; i++) {
for (j = 0; j < column; j++)
matrixFinal[power][i][j] = Tools.powerMethod(matrix[i][j], power) ;
}
It's not immediately clear what you are trying to do here. The final part seems to be trying to raise individual elements to a certain power. But this is not the same as raising a matrix to a power.
What you need to do is define a proper matrix multiplication method that can multiply two arbitrary matrices, e.g.:
int[][] multiplyMatrices (int[][] a, int[][] b) {
// compute and return a x b, similar to your existing multiplication
// algorithm, and of course taking into account the comments about
// the 'temp' output matrix above
}
Then computing a power becomes straightforward:
int[][] powerMatrix (int[][] a, int p) {
int[][] result = a;
for (int n = 1; n < p; ++ n)
result = multiplyMatrices(result, a);
return result;
}
Why not just use Math.pow?
import java.lang.Math;
Then you just have to do
matrixFinal[power][i][j] = (int) Math.pow(matrix[i][j],power); //might have to cast this to an int
How do I access an array of objects inside of an array of objects?
my code:
private boolean intersect(Polygon[] polygons, Line[] the_path, int i, int j)
{
int k = 0;
boolean intersect;
if(intersect == true)
{
for(i = 0; i < polygons.length; i++)
for(j = 0; j < polygons._lines.length; j++)
for(k = 0; k < the_path.length; k++)
intersect = polygons._lines[j].intersect(the_path[k]);
}
return intersect;
}
The intersect method in the array of lines returns a boolean, but there is a separate array of line objects in each of the polygons....how do I go about accessing that method? (note..I don't know if this exact code will do what I want yet, but either way I need to be able to access that method)
I think you accidentally left out the index into polygons (e.g. polygons[i]). Also, currently you have intersect being assigned the value of intersect() which means it is overwriting any other values given to the boolean intersect in previous loop iterations. I have added an if statement that will break out of the function immediately if that case if found instead. However, you could instead do something like intersect = intersect || ... .intersect() if you want to keep that variable.
Try this:
private boolean intersect(Polygon[] polygons, Line[] the_path, int i, int j) {
int k = 0;
for (i = 0; i < polygons.length; i++) {
for (j = 0; j < polygons[i]._lines.length; j++) {
for (k = 0; k < the_path.length; k++) {
if (polygons[i]._lines[j].intersect(the_path[k])) {
return true;
}
}
}
}
return false;
}