Find smallest int (path size) in recursive method - java

I'm trying to find the smallest path size in a maze that uses recursion.
To do this, the maze has to go through all the possible paths and then keep updating the "shortest length".
I was able to have it go through all the possible lists and print these coordinates and the path size, but I'm unable to find the minimum of values, as the path last found is always updated to be the "shortest length".
So, I was thinking of adding all of the solution path lengths to an ArrayList<Integer> list, and then create a separate static class outside of the recursion solve method, where I find the minimum and return it's value to the solve() method and proceed from there. Is this the most optimum way to do this? Or can I find the shortest length and corresponding coordinates in the solve() method?
This is what code for the recursive case:
else {
for(int i = 0; i < directions.length; i++)
{
Coord nextSpot = currentSpot.addTo(directions[i]);
if(nextSpot.validSpot(maze))
if(!newPath.contains(nextSpot)){
ArrayList<Coord> solution = //The recursive call
solve(newPath,nextSpot,goal,maze);
if(solution != null){
int shortestLength = 100; //arbitrary large length
// lengths.add(lengthSolution); ?? Possible alternative?
System.out.println(lengthSolution);
System.out.println(solution);
if( solution.size() < shortestLength ){
shortestLength = solution.size();
System.out.println(shortestLength);
}
}
}//ifs
}//for
return null;
}//else (recursive case)

int globalsteps =0;
int maze(x,y,steps) {
if(icangoup){ maze(x+1,y,steps +1);}
if(icangodown){ maze(x-1,y,steps +1);}
if(icangoleft){ maze(x,y+1,steps +1);}
if(icangoright){ maze(x,y-1,steps +1);}
if(ifoundtheexit!!!!) {
if(globalsteps == 0 || steps < globalsteps)
globalsteps = steps;
}
}
}

Related

Recursive for find shortest path using DFS in maze in java

`I got stack overflow error when using this code. i want it work if we already found the shortest path, then the recursive code will stop. the maze is contain character '#' and ' '. and if i found the shortest path, the path will mark with '.' please help thank you.
public static int getCoordinateY(String location){ //to get x coordinate
String y = location.substring(2, 4);
int coor = (y.charAt(0) - 'Q') * 10 + Character.getNumericValue(y.charAt(1));`enter code here`
return coor;
}
public boolean canPass(int y,int x) { //you can keep going if you not found # and .
if(map[y][x] == '#' || map[y][x] == '.' ) {
return false;
}
return true;
}
public Character[][] cloneArray(Character[][] src) { //copy array
int length = src.length;
Character[][] target = new Character[length][src[0].length];
for (int i = 0; i < length; i++) {
System.arraycopy(src[i], 0, target[i], 0, src[i].length);
}
return target;
}
public void finish(int x,int y){ //goal
xgoal=x;
ygoal=y;
}
public int getDistance(){ //shortest distance from shortest path
return finalDistance;
}
public void shortestPathStart(int xStart,int yStart, int xEnd, int yEnd){
set('S',xStart,yStart); //start coordinate
finish(xEnd,yEnd);
shortestPathRec(xStart+1,yStart,0,map);//to right
shortestPathRec(xStart-1,yStart,0,map);// to left
shortestPathRec(xStart,yStart+1,0,map);//to up
shortestPathRec(xStart,yStart-1,0,map);// to down
map = result; //final map with '.'
set('F',xEnd,yEnd);
print();
}
public void shortestPathRec(int x,int y,int step,Character[][] map){
if(canPass(x,y)){
step++;
Character[][] temp = cloneArray(map);
temp[x][y] = '.'; //in the maze, '.' using for flags
if(x == xgoal && y == ygoal){//if already found the goal
hasDone = true;
finalDistance = step;
result = temp;
return;
}
if(hasDone==true && finalDistance<step){ //if shortest path is found other path should be in this condition
return;
}
shortestPathRec(x+1,y,step,temp);//calltherecursive again
shortestPathRec(x-1,y,step,temp);
shortestPathRec(x,y+1,step,temp);
shortestPathRec(x,y-1,step,temp);
}
}
PROBLEM ANALYSIS
You fail to guard against physical backtracking: you move to a wall, but instead of backing up in your call stack (undo the last move), you go to the next recursion call and do the opposite move -- taking a second useless step instead of backing up to 0 useless steps. Your code will infinitely walk between those two squares until you exceed the stack limit.
REPAIR
Madify your code so that you never walk to a square you've already visited on this path. This is easy enough to research on line; Dijkstra's Algorithm is one of the earliest general solutions.
AVOIDANCE
Learn basic debugging. Among other things, insert print statements at entry and exit to each routine, printing the input parameters and return values. For extra clarity, keep an depth counter and indent the prints appropriately.

breadth first search error

public int bfs(int maxDepth){ //maxDepth = 3 works.. maxDepth = 4 gives me an error
int src = 0;
int dest = 2;
int nodes = arr[src].length - 1;
boolean[] visited = new boolean[nodes + 1];
int i;
int countDepth = 0;
int countPaths = 0;
int element;
queue.add(src);
while(!queue.isEmpty() || countDepth != maxDepth)
{
element = queue.remove();
i = element;
while(i <= nodes)
{
if(arr[element][i] > 0 && visited[i] == false)
{
queue.add(i);
visited[i] = true;
if(arr[i][element] > 0) //if it has two directions
visited[i] = false;
if(element == dest || i == dest)
countPaths++;
}
i++;
}
countDepth++;
}
return countPaths;
}
I'm trying to go 'x' amount of levels deep while counting the # of paths to the destination.
For some reason I keep getting an error:
Exception in thread "main" java.util.NoSuchElementException
at java.util.LinkedList.removeFirst(Unknown Source)
at java.util.LinkedList.remove(Unknown Source)
at Graph.bfs(Graph.java:48)
I don't understand what's going on. It seems to work when I go 3 levels deep but when I change it to 4, it doesn't work.
Change
while(!queue.isEmpty() || countDepth != maxDepth)
to
while(!queue.isEmpty() && countDepth != maxDepth)
Each graph has some maximal depth. It seems, you set maxDepth larger than it's really possible for given graph and your loop tries to continue bfsing even after handling all possible nodes (i.e when queue is empty)
UPDATE
I will try to provide answer to your second question you posted in comments even if given information actually is not enough, so, I will try to be extrasens=)
I guess, you are going to calculate all paths of length=1, of length=2.. length=givenMaxDepth|maxPossibleDepth. I saw queue data structure but I didn't see declaration - are you using the same queue for all function calls? If yes, you should clear queue after each call (best place to call queue.clear() is before return statement).
Also, I see you are using new visited array in each call and it's correct but if you actually using some global visited you also should "clear" visited after each call - in other words fill it with false.

When navigating a 2D array, check neighboring elements for valid path relative to point of entry?

The nature of this problem has changed since submission, but the question isn't fit for deletion. I've answered the problem below and marked it as a community post.
I'm writing a recursive path-navigating function and the final piece I need involves knowing which cell you came from, and determining where to go next.
The Stage
You are given a 2d array where 0's denote an invalid path and 1's denote a valid path. As far as I know, you are allowed to manipulate the data of the array you're navigating, so I mark a traveled path with 2's.
The Goal
You need to recursively find and print all paths from origin to exit. There are four mazes, some with multiple paths, dead ends, or loops.
I've written code that can correctly handle all three cases, except the method for finding the next path is flawed in that it starts at a fixed location relative to your current index, and checks for a travelled path; If you encounter it, it's supposed to retreat.
While this works in most cases, it fails in a case when the first place it checks happens to be the place you came from. At this point, it returns out and ends prematurely.
Because of this, I need to find a way to intelligently start scanning (clockwise or anti-clockwise) based on where you came from, so that that place is always the last place checked.
Here is some code describing the process (note: edge cases are handled prior to this, so we don't need to worry about that):
private static void main()
{
int StartX = ;//Any arbitrary X
int StartY = ;//Any arbitrary Y
String Path = ""; //Recursive calls will tack on their location to this and print only when an exit path is found.
int[][] myArray = ;//We are given this array, I just edit it as I go
Navigator(StartX, StartY, Path, myArray);
}
private static void Navigator(int locX, int locY, String Path, int[][] myArray)
{
int newX = 0; int newY = 0;
Path = Path.concat("["+locX+","+locY+"]");
//Case 1: You're on the edge of the maze
boolean bIsOnEdge = (locX == 0 || locX == myArray.length-1 || locY == 0 || locY == myArray[0].length-1);
if (bIsOnEdge)
{
System.out.println(Path);
return;
}
int[][] Surroundings = surroundingsFinder(locX, locY, myArray);
for (int i = 0; i <= 7; i++)
{
//Case 2: Path encountered
if (Surroundings[0][i] == 1)
{
myArray[locX][locY] = 2;
newX = Surroundings[1][i];
newY = Surroundings[2][i];
Navigator(newX, newY, myArray, Path);
}
//Case 3: Breadcrumb encountered
if (Surroundings[0][i] == 2)
{
myArray[locX][locY] = 1;
return;
}
}
}
//generates 2D array of your surroundings clockwise from N to NW
//THIS IS THE PART THAT NEEDS TO BE IMPROVED, It always starts at A.
//
// H A B
// G - C
// F E D
//
static int[][] surroundingsFinder(int locX, int locY, int[][] myArray)
{
int[][] Surroundings = new int[3][8];
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
}
}
//Can be done simpler, is done this way for clarity
int xA = locX-1; int yA = locY; int valA = myArray[xA][yA];
int xB = locX-1; int yB = locY+1; int valB = myArray[xB][yB];
int xC = locX; int yC = locY+1; int valC = myArray[xC][yC];
int xD = locX+1; int yD = locY+1; int valD = myArray[xD][yD];
int xE = locX+1; int yE = locY; int valE = myArray[xE][yE];
int xF = locX+1; int yF = locY-1; int valF = myArray[xF][yF];
int xG = locX; int yG = locY-1; int valG = myArray[xG][yG];
int xH = locX-1; int yH = locY-1; int valH = myArray[xH][yH];
int[][] Surroundings = new int[3][8];
Surroundings[0][0] = valA; Surroundings[1][0] = xA; Surroundings[2][0] = yA;
Surroundings[0][1] = valB; Surroundings[1][1] = xB; Surroundings[2][1] = yB;
Surroundings[0][2] = valC; Surroundings[1][2] = xC; Surroundings[2][2] = yC;
Surroundings[0][3] = valD; Surroundings[1][3] = xD; Surroundings[2][3] = yD;
Surroundings[0][4] = valE; Surroundings[1][4] = xE; Surroundings[2][4] = yE;
Surroundings[0][5] = valF; Surroundings[1][5] = xF; Surroundings[2][5] = yF;
Surroundings[0][6] = valG; Surroundings[1][6] = xG; Surroundings[2][6] = yG;
Surroundings[0][7] = valH; Surroundings[1][7] = xH; Surroundings[2][7] = yH;
return Surroundings;
}
Can anyone help me with this? As you can see, surroundingsFinder always finds A first, then B all the way to H. This is fine if and only if you entered from H. But if fails on cases where you entered from A, so I need to make a way to intelligently determine where to start finding. Once I know this, I can probably adapt the logic so I no longer use a 2D array of values, as well. But so far I can't come up with the logic for the smart searcher!
NOTE: I am aware that Java does not optimize middle-recursion. It seems impossible to get tail recursion working for a problem like this.
The Solution
The initial goal was to print, from start to end, all of the paths that exit the array.
An earlier rendition of the script wrote "0" on treaded locations rather than "2", but for some reason I imagined that I needed the "2" and I needed to differentiate between "treaded path" and "invalid path".
In fact, due to the recursive nature of the problem, I discovered that you can in fact solve the problem writing only 0's as you go. Also, I no longer needed to keep track of where I came from and instead of checking clockwise over a matrix, I was iterating from left to right down the 3x3 matrix surrounding me, skipping my own cell.
Here is the completed code for such a solution. It prints to console upon finding an exit (edge) and otherwise traces itself around the maze, complete with recursion. To start the function, you are given a square 2D array of 0's and 1's where 1 is a valid path and 0 is invalid. You are also given a set of coordinates where you are "dropped in" (locX, locY) and an empty string that accumulates coordinates, forming a path that is later printed out (String Path = "")
Here is the code:
static void Navigator(int locX, int locY, int[][] myArray, String Path)
{
int newX = 0;
int newY = 0;
Path = Path.concat("["+locX+","+locY+"]");
if ((locX == 0 || locX == myArray.length-1 || locY == 0 || locY == myArray[0].length-1))
{//Edge Found
System.out.println(Path);
pathCnt++;
myArray[locX][locY] = 1;
return;
}
for (int row = -1; row <= 1; row++)
{
for (int col = -1; col <= 1; col++)
{
if (!(col == 0 && row == 0) && (myArray[locX+row][locY+col] == 1))
{ //Valid Path Found
myArray[locX][locY] = 0;
Navigator(locX+row, locY+col, myArray, Path);
}
}
}
//Dead End Found
myArray[locX][locY] = 1;
return;
} System.out.println(Path);
pathCnt++;
swamp[locX][locY] = 1;
return;
}
for (int row = -1; row <= 1; row++)
{
for (int col = -1; col <= 1; col++)
{
if (!(col == 0 && row == 0) && (swamp[locX+row][locY+col] == 1))
{ //Valid Path Found
swamp[locX][locY] = 0;
Navigator(locX+row, locY+col, swamp, Path);
}
}
}
//Dead End Found
swamp[locX][locY] = 1;
return;
}
As you may determine yourself, every time we "enter" a cell, we have 8 neighbors to check for validity. First, to save on run time and to avoid going out of the array during our for loop (it can't find myArray[i][j] if i or j point it outside, and it will error out), we check for edges. Since we're given the area of our swamp we use a truth comparison statement that essentially says ("(am I on the top or left edge?) or (am I on the bottom or right edge?)"). If we ARE on an edge, we print out the Path we're holding (thanks to deep copy, we have a unique copy of the original Path that only prints if we're on an edge, and includes our full set of coordinates).
If we aren't on an edge, then we start looking around us. We start at top left and move horizontally to bottom right, with a special check to make sure we're not checking where we're standing.:
A B C
D . E
F G H
This loop checks only for 1's and only calls the function up again should that happen. Why? Because it is the second-to-last case. There is only one extra situation that will occur, and if we reach the end of the function it means we hit that case. Why write extra code (checking for 0's to specifically recognize it?
So, as I just mentioned, if we exit the for loop, it means we didn't encounter any 1's at all. It means we're surrounded by zeros! It means we've hit a dead end, and that means that all we have to do is error our away out of that instance of the function, ergo the final return;.
All in all, the final function is simple. But coming from no background and having to realize the patterns and meanings of these cases, and after several failed attempts at this, it can take quite a bit of work. I was several days at work on perfecting this.
Happy coding, Everyone!
Your issue seems to be with:
if (Surroundings[0][i] == 2)
{
myArray[locX][locY] = 1;
return;
}
Perhaps this should be changed to:
if (Surroundings[0][i] == 2)
{
// not sure why you need this if it's already 1
myArray[locX][locY] = 1;
// go to next iteration of the "i" loop
// and keep looking for next available path
continue;
}
Your recursive method will automatically return when none of the surrounding cells satisfy the condition if (Surroundings[0][i] == 1).
PS: It's conventional to name your variables using small letter as the first character. For example: surroundings, path, startX or myVar

Searching LinkedHashMap Using nested for loops

I have a LinkedHashMap like so
LinkedHashMap <Integer, ArrayList<Integer>> indexToIndecies = new LinkedHashMap <Integer ,ArrayList<Integer>>();
I have a method public int searchGraph(int baseIndex, int searchIndex, int count)
the point of this search method is; when some one enters baseIndex, which is a key, it has to find how many "clicks" it takes to get to the searchIndex. the values of the keys are the indexes to which they relate. So a "click" would be going from one key to another. So if my hashmap looks like:
0[2]
1[0, 3]
2[0, 5]
3[0, 2, 4, 5]
4[5]
5[2]
6[3, 4, 5]
7[1, 4]
to get from 0 to 5 takes two clicks.
so this is the code I have for my method:
public int searchGraph(int baseIndex, int searchIndex, int count)
{
if (baseIndex == searchIndex)
{
return count;
}
if (searchIndex > indexToIndecies.size()-1){
return -3;
}
else{
for (int i = 0; i < indexToIndecies.get(baseIndex).size(); i++)
{
for (int x = 0; x< indexToIndecies.get(baseIndex).size(); x++){
if (indexToIndecies.get(baseIndex).get(x) == searchIndex){
return count;
}
else{
count++;
}
}
baseIndex = (indexToIndecies.get(baseIndex)).get(i);
}
return count;
}
}
Works fine If The baseIndex and seachIndex I give it has an association, however if it doesn't I am not sure how to catch that... Any help will be appreciated.
Right now you're not accounting for the possibility that there may be multiple paths from the baseIndex to the searchIndex - presumably you want the shortest path if this is the case. One way to correct for this is to replace the nested for loops with a single for loop around a recursive call. Return Integer.MAX_VALUE if a path isn't found, then if your shortest path has a count of Integer.MAX_VALUE then you'll know that you weren't able to find a path. (If you DID find a path with a count of Integer.MAX_VALUE then something probably went wrong with your path-finding algorithm - you shouldn't have paths that are that long.) If you want to use nested loops instead of recursion then you can convert the recursive call into a loop by using your own stack variable.
public int searchGraph(int baseIndex, int searchIndex, int count) {
if(baseIndex == searchIndex) {
return count;
} else if(count > indexToIndecies.size()) {
return Integer.MAX_VALUE; // cycle in graph
} else {
int returnVal = Integer.MAX_VALUE;
for(int i = 0; i < indexToIndecies.get(baseIndex).size(); i++) {
int temp = searchGraph(indexToIndecies.get(baseIndex).get(i), searchIndex, count + 1);
returnVal = temp < returnVal ? temp : returnVal;
}
return returnVal;
}
}
This should return the shortest path, and if it returns Integer.MAX_VALUE then a path wasn't found.
Another option is to return an Integer instead of an int, in which case you can return a null in the case that you couldn't find a path.
Edit: SimonC pointed out in the comments that a cycle in the graph could cause a stack overflow. I've corrected for this by returning Integer.MAX_VALUE if count exceeds indexToIndecies.size(), since count shouldn't exceed the number of keys in the map.

MinMax AI for Checkers

I have created simple Checkers game in Java with minmax AI, but I doesn't work. I use recursive version of minmax, but there must be something wrong with it, because it returns moves, that aren't best, but maybe first generated.
public int minmax(int [][] board, int depth, int curPlayer){
ArrayList<Move> moves = findMoves(curPlayer, board);
if (depth == 0 || moves.size() == 0){
return heurValue(curPlayer, board);
}
int bestVal = 0;
if (curPlayer == GameCore.BLACK){
bestVal = Integer.MIN_VALUE;
curPlayer = GameCore.RED;
}else{
bestVal = Integer.MAX_VALUE;
curPlayer = GameCore.BLACK;
}
for(int i = 0; i<moves.size(); i++){
Move m = moves.get(i);
int [][] boardNew = makeMove(m, board);
int value = minmax(boardNew, depth-1, curPlayer);
board = undoMove(m, boardNew);
// computer plays as black
if (curPlayer == GameCore.BLACK){
if (value < bestVal){
bestMove = m;
bestVal = value;
}
}else{
if (value >= bestVal){
bestMove = m;
bestVal = value;
}
}
}
return bestVal;
}
If I call minmax with depth = 1 it should "return 7 values (there are 7 possible moves), but it returns only 1 if I move from 2,4 to 3,3... but when I tried to debug it, ArrayList moves has correct size. So I don't know what is wrong with it. :(
EDIT:
By "return" I mistakenly mean that first condition (when depth is 0 or moves are empty) happens only once, but if it was correct it should happen 7 times. Sorry for my bad english.
Do you know some site, where is correct recursive pseudocode for minmax (better with alpha/beta, because I will need to expand it) or could you help me to fix this? It must be only trifle.
Thank you!
You've written this to only return the best value, i.e. return bestVal; If you want it to return them all, store them in a List of some sort and change the method signature accordingly.
EDIT: So it is not a signature problem as I first thought.
I've done a quick search about the MinMax algorythm and this is what i found an article
Quickly what I think is important from this page is :
The values here represents how good a move is. So the MAX player will try to select the move with highest value in the end.
So if I'm rigth, MinMax will only return one move, the one with the bestValue.

Categories