I was trying out this algorithm for detecting groups of like pieces on a grid. It is a simple game demo that drops pieces randomly on a 12x10 grid and after each piece drop checks the grid for any groups that are three or more adjacent pieces. I am using the following code in an attempt to do this without flood fill, recursion, or stacks/queues. It seems to almost work, but will destroy squares that are not of the same type sometimes, or leave squares that should be destroyed. So, is the logic of the algorithm wrong, or is the implementation/coding wrong?
EDIT: I think this works now. See comment
public void checkMatches(int type)
{
/*
* Step 1: Iterate through each square to see how many of the same type are adjacent to it
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getType() == type) // EDITED IN CODE. Make sure current square is of correct type
{
if (i > 0) // Bounds checking
if (grid[i - 1][j].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (i < PIECES_WIDE - 1) // Bounds checking
if (grid[i + 1][j].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (j > 0) // Bounds checking
if (grid[i][j - 1].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
if (j < PIECES_TALL - 1) // Bounds checking
if (grid[i][j + 1].getType() == type)
grid[i][j].setAdj(grid[i][j].getAdj() + 1);
}
}
}
/*
* Step 2: If there are 2 or more adjacent squares with the same type then it is part of a blob and to be destroyed
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getAdj() >= 2)
grid[i][j].setDestroy(true);
}
}
/*
* Step 3: If there is only 1 adjacent, then check to see if any adjacent squares have been marked to be destroyed (part
* of a group). If so, set these to be destroyed as well.
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].getAdj() == 1)
{
if (i > 0) // Bounds checking
if (grid[i - 1][j].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (i < PIECES_WIDE - 1) // Bounds checking
if (grid[i + 1][j].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (j > 0) // Bounds checking
if (grid[i][j - 1].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
if (j < PIECES_TALL - 1) // Bounds checking
if (grid[i][j + 1].isDestroy() == true)
{
grid[i][j].setDestroy(true);
break;
}
}
}
}
/*
* Step 4: Iterate through grid and destroy the squares marked for destruction and reset all squares to 0 adjacent and
* destroy flag to false
*/
for (int i = 0; i < PIECES_WIDE; i++)
{
for (int j = 0; j < PIECES_TALL; j++)
{
if (grid[i][j].isDestroy())
destroyPiece(grid[i][j]);
grid[i][j].setAdj(0);
grid[i][j].setDestroy(false);
}
}
}
You can find groups faster when you sort the items into a bucket. You can use a spatial index for example a kd-tree.
Related
I am writing an answer to a CCC question in java, but every time I input something it just takes infinite inputs. Can anyone help me stop this?
Your task is to write a program that verifies the validity of a well plan by verifying that the borehole will not intersect itself. A two-dimensional well plan is used to represent a vertical cross-section of the borehole, and this well plan includes some drilling that has occurred starting at (0, −1) and moving to (−1, −5). You will encode in your program the current well plan shown in the figure below:
Input Format:
The input consists of a sequence of drilling command pairs. A drilling command pair begins with one of four direction indicators (d for down, u for up, l for left, and r for right) followed by a positive length. There is an additional drilling command indicated by q (quit) followed by an integer, which indicates the program should stop the execution. You can assume that the input is such that the drill point will not:
rise above the ground, nor
be more than 200 units below ground, nor
be more than 200 units to the left of the original starting point, nor
be more than 200 units to the right of the original starting point.
Output Format:
The program should continue to monitor drilling assuming that the well shown in the figure has already been made. As we can see (−1, −5) is the starting position for your program. After each command, the program must output one line with the coordinates of the new position of the drill, and one of the two comments safe, if there has been no intersection with a previous position or DANGER if there has been an intersection with a previous borehole location. After detecting and reporting a self-intersection, your program must stop.
My code is:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
ArrayList<Integer> holeX = new ArrayList<>();
ArrayList<Integer> holeY = new ArrayList<>();
String direction;
boolean danger = false;
holeX.add(0);
holeX.add(0);
for (int i = 0; i < 4; i++) {
holeX.add(i);
}
holeX.add(3);
holeX.add(3);
holeX.add(4);
holeX.add(5);
holeX.add(5);
holeX.add(5);
holeX.add(6);
for (int i = -3; i > -8; i--) {
holeX.add(7);
}
for (int i = 6; i > -2; i--) {
holeX.add(i);
}
holeX.add(-1);
holeX.add(-1);
holeY.add(-1);
holeY.add(-2);
for (int i = 0; i < 4; i++) {
holeY.add(-3);
}
holeY.add(-4);
holeY.add(-5);
holeY.add(-5);
holeY.add(-5);
holeY.add(-4);
holeY.add(-3);
holeY.add(-3);
for (int i = -3; i > -8; i--) {
holeY.add(i);
}
for (int i = 6; i > -2; i--) {
holeY.add(-7);
}
holeY.add(-6);
holeY.add(-5);
do {
direction = sc.next();
int steps = sc.nextInt();
switch (direction) {
case "d":
for (int i = holeY.get(holeY.size() - 1); i > holeY.get(holeY.size() - 1) - steps; i--) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
case "u":
for (int i = holeY.get(holeY.size() - 1); i < holeY.get(holeY.size() - 1) + steps; i++) {
holeY.add(i);
for (int j = 0; j < holeY.size() - 2; j++) {
if (Objects.equals(holeY.get(holeY.size() - 1), holeY.get(j)) && Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j))) {
danger = true;
}
}
}
break;
case "l":
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
case "r":
for (int i = holeX.get(holeX.size() - 1); i < holeX.get(holeX.size() - 1) + steps; i++) {
holeX.add(i);
for (int j = 0; j < holeX.size() - 2; j++) {
if (Objects.equals(holeX.get(holeX.size() - 1), holeX.get(j)) && i == holeY.get(j)) {
danger = true;
}
}
}
break;
default:
break;
}
if (danger == false && !"q".equals(direction)) {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + "safe");
System.out.print(" safe");
} else {
System.out.println(holeX.get(holeX.size() - 1) + " " + holeY.get(holeY.size() - 1) + " DANGER");
}
} while (!"q".equals(direction) && danger == false);
}
holeX and holeY are the coordinates of the drilled area.
Input:
l 2
d 2
r 1
q 0
Output:
-3 -5 safe
-3 -7 safe
-2 -7 safe
Well yes, you have an infinite loop. Let's take case "l" for example.
I used l and then 2.
for (int i = holeX.get(holeX.size() - 1); i > holeX.get(holeX.size() - 1) - steps; i--) {
holeX.add(i)...
You add something to the list and the condition gets re-evaluated, which leads to an infinite loop.
I don't know if it is what you want to do, but what helps is to extract the condition first into a variable, then the infinite loop stops.
all.
I am working on this problem which comes from Leetcode.
Here is the link if anyone want to see the problem: https://leetcode.com/problems/valid-sudoku/
I think I almost solve this problem, but something wrong with the "java.lang.ArrayIndexOutOfBoundsException" which I used capital comment in my code to mark it out, ==> "if (brain[((int) board[x][y]) - 1])"
I checked it many times and I think the indexes should be perfectly fine within 0~8 by doing "for( int i = 0, i < 9; i++)" and I could not find the reason.
I guess this must be easy stupid question, but I kinda spend a lot of time to find it out. Can someone help me out?
BIG THANKS to whoever help!
public class Solution {
public boolean isValidSudoku(char[][] board) {
if (board.length > 9 || board[0].length > 9 || board == null) {
return false;
}
boolean[] brain;
// 9 digits are corresponding to 1 ~ 9 ==> 0 - 1, 1 - 2 ... 8 - 9
// ex: brain[2] is checking for digit "3" , so using brain[3-1] to check "3"
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
// THE NEXT LINE IS THE PROBLEM!!!
if (brain[((int) board[x][y]) - 1]) {
// my condition failed by using:
// brain[board[x][y] - 1]
// other's condition Partially passed by using
// (still failed for final submission:
// brain[(int) (board[x][y] - '1')]
// need to compare the difference
return false;
} else {
brain[((int) board[x][y]) - 1] = true;
}
}
}
}
for (int x = 0; x < board.length; x++) {
// Reset brain
brain = new boolean[9];
for (int y = 0; y < board[0].length; y++) {
if (board[x][y] != '.') {
if (brain[((int) board[y][x]) - 1]) {
return false;
} else {
brain[((int) board[y][x]) - 1] = true;
}
}
}
}
for (int block = 0; block < 9; block++) {
// Reset brain
brain = new boolean[9];
for (int r = block / 3 * 3; r < block / 3 * 3 + 3; r++) {
for (int c = block % 3 * 3; c < block % 3 * 3 + 3; c++) {
if (board[r][c] != '.') {
if (brain[((int) board[r][c]) - 1]) {
return false;
} else {
brain[((int) board[r][c]) - 1] = true;
}
}
}
}
}
return true;
}
}
You are trying to cast a char as int. Try to manually cast these values and you will notice that 0=48 and 9=57, which i guess should be the cause of your exception.
You might want to check if the value in there represents a number and get the numeric value of the char by using the Character#getNumericValue method.
if (Character.isDigit(board[x][y]) &&
brain[Character.getNumericValue(board[x][y])) - 1]) {
...
}
i am try to implement 8 queen using depth search for any initial state it work fine for empty board(no queen on the board) ,but i need it to work for initial state if there is a solution,if there is no solution for this initial state it will print there is no solution
Here is my code:
public class depth {
public static void main(String[] args) {
//we create a board
int[][] board = new int[8][8];
board [0][0]=1;
board [1][1]=1;
board [2][2]=1;
board [3][3]=1;
board [4][4]=1;
board [5][5]=1;
board [6][6]=1;
board [7][7]=1;
eightQueen(8, board, 0, 0, false);
System.out.println("the solution as pair");
for(int i=0;i<board.length;i++){
for(int j=0;j<board.length;j++)
if(board[i][j]!=0)
System.out.println(" ("+i+" ,"+j +")");
}
System.out.println("the number of node stored in memory "+count1);
}
public static int count1=0;
public static void eightQueen(int N, int[][] board, int i, int j, boolean found) {
long startTime = System.nanoTime();//time start
if (!found) {
if (IsValid(board, i, j)) {//check if the position is valid
board[i][j] = 1;
System.out.println("[Queen added at (" + i + "," + j + ")");
count1++;
PrintBoard(board);
if (i == N - 1) {//check if its the last queen
found = true;
PrintBoard(board);
double endTime = System.nanoTime();//end the method time
double duration = (endTime - startTime)*Math.pow(10.0, -9.0);
System.out.print("total Time"+"= "+duration+"\n");
}
//call the next step
eightQueen(N, board, i + 1, 0, found);
} else {
//if the position is not valid & if reach the last row we backtracking
while (j >= N - 1) {
int[] a = Backmethod(board, i, j);
i = a[0];
j = a[1];
System.out.println("back at (" + i + "," + j + ")");
PrintBoard(board);
}
//we do the next call
eightQueen(N, board, i, j + 1, false);
}
}
}
public static int[] Backmethod(int[][] board, int i, int j) {
int[] a = new int[2];
for (int x = i; x >= 0; x--) {
for (int y = j; y >= 0; y--) {
//search for the last queen
if (board[x][y] != 0) {
//deletes the last queen and returns the position
board[x][y] = 0;
a[0] = x;
a[1] = y;
return a;
}
}
}
return a;
}
public static boolean IsValid(int[][] board, int i, int j) {
int x;
//check the queens in column
for (x = 0; x < board.length; x++) {
if (board[i][x] != 0) {
return false;
}
}
//check the queens in row
for (x = 0; x < board.length; x++) {
if (board[x][j] != 0) {
return false;
}
}
//check the queens in the diagonals
if (!SafeDiag(board, i, j)) {
return false;
}
return true;
}
public static boolean SafeDiag(int[][] board, int i, int j) {
int xx = i;
int yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy++;
xx++;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy--;
xx--;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy--;
xx++;
}
xx = i;
yy = j;
while (yy >= 0 && xx >= 0 && xx < board.length && yy < board.length) {
if (board[xx][yy] != 0) {
return false;
}
yy++;
xx--;
}
return true;
}
public static void PrintBoard(int[][] board) {
System.out.print(" ");
for (int j = 0; j < board.length; j++) {
System.out.print(j);
}
System.out.print("\n");
for (int i = 0; i < board.length; i++) {
System.out.print(i);
for (int j = 0; j < board.length; j++) {
if (board[i][j] == 0) {
System.out.print(" ");
} else {
System.out.print("Q");
}
}
System.out.print("\n");
}
}
}
for example for this initial state it give me the following error:
Exception in thread "main" java.lang.StackOverflowError
i am stuck, i think the error is infinite call for the method how to solve this problem.
any idea will be helpful,thanks in advance.
note:the broad is two dimensional array,when i put (1) it means there queen at this point.
note2:
we i put the initial state as the following it work:
board [0][0]=1;
board [1][1]=1;
board [2][2]=1;
board [3][3]=1;
board [4][4]=1;
board [5][5]=1;
board [6][6]=1;
board [7][1]=1;
[EDIT: Added conditional output tip.]
To add to #StephenC's answer:
This is a heck of a complicated piece of code, especially if you're not experienced in programming Java.
I executed your code, and it outputs this over and over and over and over (and over)
back at (0,0)
01234567
0
1 Q
2 Q
3 Q
4 Q
5 Q
6 Q
7 Q
back at (0,0)
And then crashes with this
Exception in thread "main" java.lang.StackOverflowError
at java.nio.Buffer.<init>(Unknown Source)
...
at java.io.PrintStream.print(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at Depth.eightQueen(Depth.java:56)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
at Depth.eightQueen(Depth.java:60)
...
My first instinct is always to add some System.out.println(...)s to figure out where stuff is going wrong, but that won't work here.
The only two options I see are to
Get familiar with a debugger and use it to step through and analyze why it's never stopping the loop
Break it down man! How can you hope to deal with a massive problem like this without breaking it into digestible chunks???
Not to mention that the concept of 8-queens is complicated to begin with.
One further thought:
System.out.println()s are not useful as currently implemented, because there's infinite output. A debugger is the better solution here, but another option is to somehow limit your output. For example, create a counter at the top
private static final int iITERATIONS = 0;
and instead of
System.out.println("[ANUMBERFORTRACING]: ... USEFUL INFORMATION ...")
use
conditionalSDO((iITERATIONS < 5), "[ANUMBERFORTRACING]: ... USEFUL INFORMATION");
Here is the function:
private static final void conditionalSDO(boolean b_condition, String s_message) {
if(b_condition) {
System.out.println(s_message);
}
}
Another alternative is to not limit the output, but to write it to a file.
I hope this information helps you.
(Note: I edited the OP's code to be compilable.)
You asked for ideas on how to solve it (as distinct from solutions!) so, here's a couple of hints:
Hint #1:
If you get a StackOverflowError in a recursive program it can mean one of two things:
your problem is too "deep", OR
you've got a bug in your code that is causing it to recurse infinitely.
In this case, the depth of the problem is small (8), so this must be a recursion bug.
Hint #2:
If you examine the stack trace, you will see the method names and line numbers for each of the calls in the stack. This ... and some thought ... should help you figure out the pattern of recursion in your code (as implemented!).
Hint #3:
Use a debugger Luke ...
Hint #4:
If you want other people to read your code, pay more attention to style. Your indentation is messed up in the most important method, and you have committed the (IMO) unforgivable sin of ignoring the Java style rules for identifiers. A method name MUST start with a lowercase letter, and a class name MUST start with an uppercase letter.
(I stopped reading your code very quickly ... on principle.)
Try to alter your method IsValid in the lines where for (x = 0; x < board.length - 1; x++).
public static boolean IsValid(int[][] board, int i, int j) {
int x;
//check the queens in column
for (x = 0; x < board.length - 1; x++) {
if (board[i][x] != 0) {
return false;
}
}
//check the queens in row
for (x = 0; x < board.length - 1; x++) {
if (board[x][j] != 0) {
return false;
}
}
//check the queens in the diagonals
if (!SafeDiag(board, i, j)) {
return false;
}
return true;
}
So I have this university assignment to solve Sudoku... I read about Algorithm X and Dancing algorithm, but they didn't help me.
I need to make it with backtracking. I hard-coded some of the indexes in the two dimensional array with numbers on places given from Wikipedia (so I am sure that it's solvable).
The code I got is the following:
public void solveSudoku(int row, int col)
{
// clears the temporary storage array that is use to check if there are
// dublicates on the row/col
for (int k = 0; k < 9; k++)
{
dublicates[k] = 0;
}
// checks if the index is free and changes the input number by looping
// until suitable
if (available(row, col))
{
for (int i = 1; i < 10; i++)
{
if (checkIfDublicates(i) == true)
{
board[row][col] = i;
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
board[row][col] = 0;
}
}
}
// goes to the next row/col
else
{
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
}
}
/**
* Checks if the spot on the certain row-col index is free of element
*
* #param row
* #param col
* #return
*/
private boolean available(int row, int col)
{
if (board[row][col] != 0)
return false;
else
return true;
}
/**
* Checks if the number given is not already used in this row/col
*
* #param numberToCheck
* #return
*/
private boolean checkIfDublicates(int numberToCheck)
{
boolean temp = true;
for (int i = 0; i < dublicates.length; i++)
{
if (numberToCheck == dublicates[i])
{
temp = false;
return false;
}
else if (dublicates[i] == 0)
{
dublicates[i] = numberToCheck;
temp = true;
return true;
}
}
return temp;
}
I am getting StackOverflow on
// goes to the next row/col
else
{
if (row == 8)
solveSudoku(0, col + 1);
else if (col == 8)
solveSudoku(row + 1, 0);
else
solveSudoku(row, col + 1);
}
which means that I have to stop the recursion at some point, but I can't figure it out how!
If you find any other mistakes in the solve() function - let me know. Because I am not sure I understand the "backtracking" thing completely...
You can stop recursion for example if you keep track of the current recursion depth
public void solveSudoku(int row, int col, int recursionDepth) {
// get out of here if too much
if (recursionDepth > 15) return;
// regular code...
// at some point call self with increased depth
solveSudoku(0, col + 1, recursionDepth + 1);
}
And if you find any other mistakes in the solve() function - let me know.
Too much code :)
This is roughly the way I've done this in the past.
Whenever all the definite moves have been taken and there is a choice of equally good next moves:
copy your grid data structure and push it onto a stack.
take the first candidate move and continue solving recursively
Whereever you get stuck:
pop the saved grid off the stack
take the next candidate move.
I made it in a more simple way:
public void solve(int row, int col)
{
if (row > 8)
{
printBoard();
System.out.println();
return;
}
if (board[row][col] != 0)
{
if (col < 8)
solve(row, col + 1);
else
solve(row + 1, 0);
}
else
{
for (int i = 0; i < 10; i++)
if (checkRow(row, i) && checkCol(col, i))
//&& checkSquare(row, col, i))
{
board[row][col] = i;
if (col < 8)
solve(row, col + 1);
else
solve(row + 1, 0);
}
board[row][col] = 0;
}
}
private boolean checkRow(int row, int numberToCheck)
{
for (int i = 0; i < 9; i++)
if (board[row][i] == numberToCheck)
return false;
return true;
}
private boolean checkCol(int col, int numberToCheck)
{
for (int i = 0; i < 9; i++)
if (board[i][col] == numberToCheck)
return false;
return true;
}
I'm not sure why you say that Dancing Links and Algorithm X were not useful.
Do you mean that you were not able to map Sudoku to an instance of the Exact Cover problem that Algorithm X is designed to solve?
Or that it is a too complicated approach for what you need??
If the former is the case, you might want to look at: A Sudoku Solver in Java implementing Knuth’s Dancing Links Algorithm. It's quite clear and explains also the reasoning behind.
N.B. Algorithm X is a backtracking algorithm so, if that's your only requirement, you can definitely use this approach.
Hope this can help.
I have written a code which first get some points(has x ,y) and then I will check all possible triangles with those points and I will check that the specific point is in a triangle or not(with determinate) but I have problem with this part of code which finds the external points and internal points.it doesn't work well.please help me thanks.
public void externalPoints(List<Point> pointList) {
// this method will check that a point is in a (n-1)(n-2)(n-3)/6 triangles or not
int n = pointList.size();
if (n <= 2) {
System.out.println("null");
} else if (n == 3) {
drawingLine();
} else {
for (int i = 0; i < n; i++) {
for (int j = 1; j < n; j++) {
for (int k = 2; k < n; k++) {
for (int m = 3; m < n; m++) {
if (isPointInTriangle(pointList.get(i), pointList.get(j), pointList.get(k), pointList.get(m)) == true) {
System.out.println("is in the triangle");
break;
} else {
System.out.println("is not in a triangle");
newList.add(pointList.get(i));
}
}
}
}
}
}
}
Also isInTriangle method is like this site :link text
Can you explain why it isn't working well?
It seems that your method of iterating over points is a little dodgy. For example, if n == 5, your program will evaluate isPointInTriangle for i = j = k = m = 4, meaning that it's trying to figure out whether Point 4 is inside a triangle formed from vertices 4,4,4. If you're using the first method in your link, isPointInTriangle(4,4,4,4) will return true, even though the shape you gave it isn't actually a triangle... you probably want to assert that your vertices are distinct points.