i want to add to my code an exception in the bottom part
if(legalNeighbor(map,i1,j1,i1,j2)==false&&i1!=i2&&j1!=j2){
return 0;
what i want to do is: if the "if" above is true, instead of doing "return 0" i will throw an exception that will check the code from this point
if (locationNeighbor(map,i1+1,j1,i1,j1)==2&&map2[i1+1][j1]==-1){ //down
map2[i1+1][j1]=counter;
return distance(map,i1+1,j1,i2,j2,map2,counter+1);
}
if (locationNeighbor(map,i1,j1+1,i1,j1)==3&&map2[i1][j1+1]==-1){
and then again if the "if" happens i will check the code from this area
if (locationNeighbor(map,i1,j1+1,i1,j1)==3&&map2[i1][j1+1]==-1){ //right
map2[i1][j1+1]=counter;
return distance(map,i1,j1+1,i2,j2,map2,counter+1);
}
and then last time i check
if (locationNeighbor(map,i1,j1-1,i1,j1)==4&&map2[i1][j1-1]==-1){ //left
map2[i1][j1-1]=counter;
return distance(map,i1,j1-1,i2,j2,map2,counter+1);
}
this is my code
public static int distance(int[][] map, int i1, int j1, int i2, int j2, int[][]map2, int counter) {
if(legalNeighbor(map,i1,j1,i2,j2)==true){ // if its 1 step before the end
map2[i2][j2]=counter; // put the last number
}
if (locationNeighbor(map,i1-1,j1,i1,j1)==1&&map2[i1-1][j1]==-1){ //up
map2[i1-1][j1]=counter;
return distance(map,i1-1,j1,i2,j2,map2,counter+1);
}
if (locationNeighbor(map,i1+1,j1,i1,j1)==2&&map2[i1+1][j1]==-1){ //down
map2[i1+1][j1]=counter;
return distance(map,i1+1,j1,i2,j2,map2,counter+1);
}
if (locationNeighbor(map,i1,j1+1,i1,j1)==3&&map2[i1][j1+1]==-1){ //right
map2[i1][j1+1]=counter;
return distance(map,i1,j1+1,i2,j2,map2,counter+1);
}
if (locationNeighbor(map,i1,j1-1,i1,j1)==4&&map2[i1][j1-1]==-1){ //left
map2[i1][j1-1]=counter;
return distance(map,i1,j1-1,i2,j2,map2,counter+1);
}
print(map2);
if(legalNeighbor(map,i1,j1,i1,j2)==false&&i1!=i2&&j1!=j2){
return 0;
}
else{
int x=map2[i2][j2];
return x;
}
}
is this even possible with exception?
Anything is possible, but it's probably not a good idea. Exceptions should be truly exceptional, not something that is likely to happen.
Not only that, but they are expensive in terms of performance. You should not be using exceptions to control flow logic.
Why isn't a true/false return from a method named isLegalNeighbor not sufficient?
You really have two methods here: One to calculate distance and another to determine a legal neighbor. Split them up. A method should do one thing well, and its name should make clear what that is.
One more bit: I find your code very hard to read. I would start thinking more about style and how to write more readable code if I were you.
Forget about the exception, it's probably not what you want here. First explain what your are trying to achieve. This is completely unobvious from your code.
It's strange that the first if-statement sets a value in map2 but does not return. This means the value might be overwritten by the code below. Is that intended?
I also think there's an error in the line:
if(legalNeighbor(map,i1,j1,i1,j2)==false&&i1!=i2&&j1!=j2){
The 4th argument i1 should be i2, right?
To make your code more readable you should introduce instance fields and methods with meaningful names. If your tutor is forcing you to use static methods and meaningless names like i1 etc you should fire him/her. :-D
Here's an idea of what I mean:
// I chose weird names because I really don't know what's in these arrays
// You should make it clear from the name what it represents
private int[][] fooBar;
private int[][] bazBop;
public int distance(int fromX, int fromY, int toX, int toY, int counter) {
if (legalNeighbor(fromX, fromY, toX, toY) == true) { // if its 1 step before the end
bazBop[toX][toY] = counter; // put the last number
}
int newX = fromX - 1;
int newY = fromY;
if (locationNeighbor(newX, newY, fromX, fromY) == 1 && bazBop[newX][newY] == -1) { //up
bazBop[newX][newY] = counter;
return distance(newX, newY, toX, toY, counter + 1);
}
// ...
}
Related
This is the problem:
You have maps of parts of the space station, each starting at a prison exit and ending at the door to an escape pod. The map is represented as a matrix of 0s and 1s, where 0s are passable space and 1s are impassable walls. The door out of the prison is at the top left (0,0) and the door into an escape pod is at the bottom right (w-1,h-1).
Write a function answer(map) that generates the length of the shortest path from the prison door to the escape pod, where you are allowed to remove one wall as part of your remodeling plans. The path length is the total number of nodes you pass through, counting both the entrance and exit nodes. The starting and ending positions are always passable (0). The map will always be solvable, though you may or may not need to remove a wall. The height and width of the map can be from 2 to 20. Moves can only be made in cardinal directions; no diagonal moves are allowed.
To Summarize the problem: It is a simple rat in a maze problem with rat starting at (0,0) in matrix and should reach (w-1,h-1). Maze is a matrix of 0s and 1s. 0 means path and 1 means wall.You have the ability to remove one wall(change it from 0 to 1). Find the shortest path.
I've solved the problem but 3 of 5 testcases fail and I don't know what those test cases are. and I'm unable to figure out why. Any help would be greatly appreciated.Thanks in Advance. Here is my code:
import java.util.*;
class Maze{//Each cell in matrix will be this object
Maze(int i,int j){
this.flag=false;
this.distance=0;
this.x=i;
this.y=j;
}
boolean flag;
int distance;
int x;
int y;
}
class Google4_v2{
public static boolean isPresent(int x,int y,int r,int c)
{
if((x>=0&&x<r)&&(y>=0&&y<c))
return true;
else
return false;
}
public static int solveMaze(int[][] m,int x,int y,int loop)
{
int r=m.length;
int c=m[0].length;
int result=r*c;
int min=r*c;
Maze[][] maze=new Maze[r][c];//Array of objects
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
maze[i][j]=new Maze(i,j);
}
}
Queue<Maze> q=new LinkedList<Maze>();
Maze start=maze[x][y];
Maze[][] spare=new Maze[r][c];
q.add(start);//Adding source to queue
int i=start.x,j=start.y;
while(!q.isEmpty())
{
Maze temp=q.remove();
i=temp.x;j=temp.y;
int d=temp.distance;//distance of a cell from source
if(i==r-1 &&j==c-1)
{
result=maze[i][j].distance+1;
break;
}
maze[i][j].flag=true;
if(isPresent(i+1,j,r,c)&&maze[i+1][j].flag!=true)//check down of current cell
{
if(m[i+1][j]==0)//if there is path, add it to queue
{
maze[i+1][j].distance+=1+d;
q.add(maze[i+1][j]);
}
if(m[i+1][j]==1 && maze[i+1][j].flag==false && loop==0)//if there is no path, see if breaking the wall gives a path.
{
int test=solveMaze(m,i+1,j,1);
if(test>0)
{
test+=d+1;
min=(test<min)?test:min;
}
maze[i+1][j].flag=true;
}
}
if(isPresent(i,j+1,r,c)&&maze[i][j+1].flag!=true)//check right of current cell
{
if(m[i][j+1]==0)
{
maze[i][j+1].distance+=1+d;
q.add(maze[i][j+1]);
}
if(m[i][j+1]==1 && maze[i][j+1].flag==false && loop==0)
{
int test=solveMaze(m,i,j+1,1);
if(test>0)
{
test+=d+1;
min=(test<min)?test:min;
}
maze[i][j+1].flag=true;
}
}
if(isPresent(i-1,j,r,c)&&maze[i-1][j].flag!=true)//check up of current cell
{
if(m[i-1][j]==0)
{
maze[i-1][j].distance+=1+d;
q.add(maze[i-1][j]);
}
if(m[i-1][j]==1 && maze[i-1][j].flag==false && loop==0)
{
int test=solveMaze(m,i-1,j,1);
if(test>0)
{
test+=d+1;
min=(test<min)?test:min;
}
maze[i-1][j].flag=true;
}
}
if(isPresent(i,j-1,r,c)&&maze[i][j-1].flag!=true)//check left of current cell
{
if(m[i][j-1]==0)
{
maze[i][j-1].distance+=1+d;
q.add(maze[i][j-1]);
}
if(m[i][j-1]==1 && maze[i][j-1].flag==false && loop==0)
{
int test=solveMaze(m,i,j-1,1);
if(test>0)
{
test+=d+1;
min=(test<min)?test:min;
}
maze[i][j-1].flag=true;
}
}
}
return ((result<min)?result:min);
}
public static int answer(int[][] m)
{
int count;
int r=m.length;
int c=m[0].length;
count=solveMaze(m,0,0,0);
return count;
}
public static void main(String[] args)
{
Scanner sc=new Scanner(System.in);
System.out.println("enter row size ");
int m=sc.nextInt();
System.out.println("enter column size ");
int n=sc.nextInt();
int[][] maze=new int[m][n];
System.out.println("Please enter values for maze");
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
maze[i][j]=sc.nextInt();
}
}
int d=answer(maze);
System.out.println("The maze can be solved in "+d+" steps");
}
}
Found the problem. maze[i][j].flag=true; needs to be put as soon as the cell is visited, inside the if(m[i+1][j]==0) condition. Otherwise, the distance for same cell can be added by more than one cells
Unfortunately it's quite hard to help you because your code is very difficult to read. The variables are generally single characters which makes it impossible to know what they are supposed to represent. Debugging it would be more help than most of us are willing to give :-)
I suggest you go about debugging your code as follows:
Split your solveMaze method into a number of smaller methods that each perform much simpler functions. For example, you have very similar code repeated 4 times for each direction. Work to get that code in a single method which can be called 4 times. Move your code to create the array into a new method. Basically each method should do one simple thing. This approach makes it much easier to find problems when they arise.
Write unit tests to ensure each of those methods do exactly what you expect before attempting to calculate the answer for entire mazes.
Once all the methods are working correctly, generate some mazes starting from very simple cases to very complex cases.
When a case fails, use an interactive debugger to walk through your code and see where it is going wrong.
Good luck.
I am working on my maze game and I've almost got the generating of the maze. The only problem I have is that when I try to run my init method, it gives me a stack overflow error. I think this has to do with the corStack getting too large, but I can't find the cause of this problem. Here's the code:
The maze generating:
public void carveMaze(Stack<Integer> corStack, int currentX, int currentY)
{
ArrayList<Integer> corList = getNeighbours(currentX, currentY);
Random randomGen = new Random();
while (checkForUnvisited()) {enter code here
if (corList.size() > 0) {
boolean goodNumber = false;
int newY = 0;
int newX = 0;
int index = 0;
index = randomGen.nextInt(corList.size());
if (index % 2 != 0) {
newY = corList.get(index);
goodNumber = true;
}
goodNumber = false;
while (!goodNumber) {
index = randomGen.nextInt(corList.size());
if (index % 2 == 0) {
newX = corList.get(index);
goodNumber = true;
}
}
corStack.push(currentY);
corStack.push(currentX);
if (newX > currentX) {
maze[newY][newX - 1].setStatus(Cell.WEG);
maze[newY][newX - 1].setVisited(true);
maze[newY][newX].setVisited(true);
} else if (newX < currentX) {
maze[newY][newX + 1].setStatus(Cell.WEG);
maze[newY][newX + 1].setVisited(true);
maze[newY][newX].setVisited(true);
} else if (newY > currentY) {
maze[newY - 1][newX].setStatus(Cell.WEG);
maze[newY - 1][newX].setVisited(true);
maze[newY][newX].setVisited(true);
} else if (newY < currentY) {
maze[newY + 1][newX].setStatus(Cell.WEG);
maze[newY + 1][newX].setVisited(true);
maze[newY][newX].setVisited(true);
}
maze[currentY][currentX].setVisited(true);
currentX = newX;
currentY = newY;
carveMaze(corStack, currentX, currentY);
} else {
if (!corStack.isEmpty()) {
currentX = (int) corStack.pop();
currentY = (int) corStack.pop();
carveMaze(corStack, currentX, currentY);
}
}
}
}
The cell Class:
package javaapplication23;
public class Cell {
public static final int SPELER = 2;
public static final int WEG = 0;
public static final int MUUR = 1;
public static final int BAZOOKA = 3;
private int status;
private boolean visited;
Cell(int status, boolean visited)
{
this.status = status;
this.visited = visited;
}
public int getStatus()
{
return status;
}
public boolean getVisited()
{
return visited;
}
public void setStatus(int status)
{
this.status = status;
}
public void setVisited(boolean visited)
{
this.visited = visited;
}
}
I double checked everything but I can't find the cause of the problem. The problem starts when I put the else{if(!corstack.isempty)} section after the if(corList.size() > 0) statement so I know it's in there somewhere.
stacktrace:
Exception in thread "main" java.lang.StackOverflowError
at java.util.ArrayList.grow(ArrayList.java:239)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:220)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:212)
at java.util.ArrayList.add(ArrayList.java:443)
at javaapplication23.MazeManager.getNeighbours(MazeManager.java:154)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:55)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:105)
at javaapplication23.MazeManager.carveMaze(MazeManager.java:110)
You are calling carveMaze() within carveMaze() and this causes the StackOverflowError. Everytime the method is called, its variables take up space in the stack, which are garbage collected when the method completes. In your case, before the method completes, you are calling it again and therefore your stack gets filled-up more before it had time to empty-up. Your stack gets full ("overflown") thus the Error. If you want to call carveMaze() continuously, you'd be better off with a loop of some sort.
Before you go to any trouble changing the structure of your code, you need to be sure there is no faulty logic within your algorithm implementation. This is partly just stating the obvious, but it's worth mentioning:
Try your code with minimally sized mazes and see if they complete without an overflow. If they consistently work, then your logic might be sound. If they don't, then there's faulty logic in finding an exit condition for your recursive loop (and that will guarantee an overflow every time).
Try to pinpoint (using your debugger) why these minimal mazes are not finding a termination condition (ie. the case where the recursive calls will stop happening). This can be difficult to do, but is made easier if you are working with minimal reproducible examples - ie. very small mazes.
Sometimes it can also help to put some conditional blocks into your source solely to allow you to set a breakpoint that can be triggered only when a condition is met (ie. allowing you to break when a list is under a certain size for example).
Once you get it working for some mazes, Unit Testing each part of your code is a great way to ensure that special circumstances ("corner cases") aren't causing your code to derail on seemingly arbitrary occasions.
Once small examples work successfully for many inputs, you can start creating larger mazes. If the stack overflow is only happening on very large mazes then its possibly just an issue with the size of the stack.
At that point, if this appears to definitely be the problem, try increasing your java stack size:
java -Xss4m Test
for more info look here: How to increase the Java stack size?
If increasing the stack size solves the problem then all may be good: you can either work around your issues by increasing the stack size every time you run your code, or change the code to remove the recursion, but at least you'll know the logic does find a termination condition eventually given enough memory resources to work with.
The general approach to removing recursion is to use a loop and your own Stack data structure rather than the virtual machine's stack. Further info here:
Way to go from recursion to iteration
I think the most important point is that debugging code is easier to do with a debugger than just from reading it, which makes you, the writer of the code, the person in the best position to fix it.
Besides, debugging your code is usually more fun than writing questions asking other people to help.
Hope these ideas help you solve your problem.
Looks like your program is calling carveMaze() recursively without any base conditions and thus you are getting StackOverFlow Issue.Can you identify a case when this function should stop calling itself.Please find an example here
I found it :) the fault was with the getting of random new neighbour. I inserted the coordinates like x, y, x, y, x, y etc. in the neighbour list and then chose random coordinates. instead of getting the x and following y, i chose a random x with random y :0
thanks all!
Ok so I am new to programming(Don't laugh at me if I ask a question very easy).
A sample of my code is as follows:
public int calcGCF(int mya, int mye, int myf, int myj)
{
x = myj * myf;
y = mye* mya;
while(x != 0 && y != 0)
{
if(x % y == 0)
{
remainder = y;
}
int gcf;
gcf = y;
y = x % y;
x = gcf;
}
}
Ok. So what this code is for is to potentially solve the derivative of any problem that the user inputs. Part of solving the derivative is getting a gcf of 2 numbers and factoring it out. When I try to compile this code, it says that I am missing a return statement. I understand what that is, but when I try to say "return remainder;" it says it may not have been initialized. Can somebody please tell me what I am doing wrong in this code, and help me with what I should put in my return statement? Thank You! By the way this is with java code.
Where are the variables x, y, and remainder declared? I don't see an int remainder; statement anywhere in the code you posted. There's also no return statement in the method, so it will not compile.
Local variables (variables that you declare inside a method) must be initialized with a value before you use them anywhere where you read the value. If you do this, for example:
public int method(int a) {
int value;
if (a > 10) {
value = 99;
}
return value;
}
Then you will get the same error as you are getting, because in case a is not greater than 10, the variable value isn't assigned any value when you reach the return statement - so Java doesn't know what value to return then.
You must make sure that value is assigned a value in any possible case.
As you wish you can return the remainder. Just initialize your remainder to a value. eg: remainder=0;
I understand what that is, but when I try to say "return remainder;" it says it may not have been initialized.
So you simply need to declare, at the top of your code, something like:
remainder = 0;
I would also think about naming your variables a little more appropriately than just myj.
I can't seem to figure this one out. I need to count how many numbers below a given number in which it is divisible.
Here is what I've tried:
public int testing(int x) {
if (x == 0) {
System.out.println("zero");
return x;
}
else if ((x % (x-1)) == 0) {
System.out.println("does this work?");
x--;
}
return testing(x-1);
}
That doesn't work and I don't know where to go from here. Anyone know what to do?
This is what is wrong:
public int testing(int x) {
If you want to make it recursive, you need to pass both the number to test and the number that you are currently checking. The first one will not change through the recursion, the second one will decrement. You cannot do what you express with only one parameter (unless you use a global variable).
This is not a task that should be solved with recursion.
If you MUST use recursion, the simplest way to do it is to have a second parameter, which is essentially an "I have checked until this number". Then you can increase/decrease this (depending on if you start at 0 or the initial number) and call the recursive on that.
Thing is, Java isn't a functional language, so doing all this is actually kind of dumb, so whoever gave you this exercise probably needs a bop on the head.
Your problem is that your expression x % (x - 1) is using the "current" value of x, which decrements on every call to the recursive function. Your condition will be false all the way down to 2 % (2 - 1).
Using a for loop is a much better way to handle this task (and look at the Sieve of Eratosthenes), but if you really have to use recursion (for homework), you'll need to pass in the original value being factored as well as the current value being tried.
You have a problem with your algorithm. Notice the recursion only ends when x == 0, meaning that your function will always return 0 (if it returns at all).
In addition, your algorithm doesn't seem to make any sense. You are basically trying to find all factors of a number, but there's only one parameter, x.
Try to make meaningful names for your variables and the logic will be easier to read/follow.
public int countFactors(int number, int factorToTest, int numFactors)
{
if (factorToTest == 0) // now you are done
return numFactors;
else
// check if factorToTest is a factor of number
// adjust the values appropriately and recurse
}
There is no need to use recursion here. Here's a non-recursive solution:
public int testing(int n) {
int count = 0;
for (int i = 1; i < n; i++)
if (n % i == 0)
count++;
return count;
}
BTW, you should probably call this something other than testing.
Using recursion:
private static int getFactorCount(int num) {
return getFactorCount(num, num - 1);
}
private static int getFactorCount(int num, int factor) {
return factor == 0 ? 0 : (num % factor == 0 ? 1 : 0)
+ getFactorCount(num, factor - 1);
}
public static void main(String[] args) {
System.out.println(getFactorCount(20)); // gives 5
System.out.println(getFactorCount(30)); // gives 7
}
I dont understand why this is forward recursion:
int count(int x) {
if(x<=0) return 0;
return 1 + count(x - 1);
}
It's a question on a practice exam, and the answer is that its forward recursion. Why is this the case? How could I distinguish between the two?
You're doing an addition after calling yourself. Tail recursion means absolutely nothing can be after
If you understand the implementation, it's clear why.
Say we call count for the first time from main, which is at program counter 0xAAA. It then does most of its method. We'll say the recursive call to count is at 0xBBB for this stack frame. If you're using tail recursion, when calling itself, it can set the return address as 0xAAA (just go straight to the code that called me). If it's doing anything after, it must set the return address as 0xBBC (the address of the addition). Because it doesn't need stack frames to store return addresses, it's also much easier to transform the recursion to iteration. When count calls itself, it can just jump to the beginning of the method.
The solution (to the trivial example) is to build up the result in another parameter:
int count(int x, int res) {
if(x<=0) return res;
return count(x - 1, res + 1);
}
Note we do nothing after.
Did you look at this SO question, tail vs forward recursion?
Matthew has the answer,and the long form would be that:
int count(int x) {
if(x<=0) return 0;
return 1 + count(x - 1);
}
can be written as (and is expanded as something like):
int count(int x) {
if(x<=0) return 0;
int tmp_result = count(x - 1);
return 1 + tmp_result; // e.g. recursion is not last
}