Maze problem

Hey guys,

I am working on the typical maze problem that I'm sure most students have had to solve at one point. We have to find all paths whose cost (number of moves/hops) < X. I have solved it recursively but am at a lost as to how to find all paths with an iterative solution. Our instructor hinted stack and queue might be a good option, but I can only think of how to find one path. To do that I would just search in one direction until I hit a wall then pop back searching different ways until I found the exit. How can I keep track of all valid paths? Thanks.

[581 byte] By [neolithic15a] at [2007-10-1 5:59:00]
# 1

Stack solution:

Create an object that gives each point a unique ID and a direction. As you travel, push each PointDir onto a stack. At a dead end, pop the stack, pick an untried direction and push again. If there are no untried directions, discard and pop the previous.

At goal, copy the stack to a solutions list and then proceed as if it were a dead end.

Unique IDs are easy - use a class static, initialized to zero. The assignID method copies the value and increments the static.

MartinRineharta at 2007-7-9 14:15:26 > top of Java-index,Java Essentials,Java Programming...
# 2
A stack based solution isn't iterative though. It's just a recursive solution where the normal callstack is replaced by your own stack.
-Kayaman-a at 2007-7-9 14:15:26 > top of Java-index,Java Essentials,Java Programming...
# 3

^^

That sounds like a good plan. So you are saying just create a point class and that has a direction and a coordinate and push those on to the stack? Keep doing that until you find the end, copy the solution, then pop back and repeat, thus trying every direction for every point?

By iteration my professor really meant not recursion. He wants to have some loops and absolutely no method which calls itself.

neolithic15a at 2007-7-9 14:15:26 > top of Java-index,Java Essentials,Java Programming...
# 4

Are you suggesting that I store the direction that the point came from i.e. in the maze below:

0 0

0 0

The top right point would look like this:

1,0 East.

I don't think that would work b/c of a scenario like this:

0 0 0 0 1

1 1 0 0 1

1 1 1 0 0

Where there are obviously 2 unique paths but they both arrive at the 0 on the bottom row second from the right from the same direction (and even the exit with is the very bottom right).

neolithic15a at 2007-7-9 14:15:26 > top of Java-index,Java Essentials,Java Programming...
# 5

> A stack based solution isn't iterative though. It's

> just a recursive solution where the normal callstack

> is replaced by your own stack.

Maybe a recursive solution is iterative, where the iterativeness is hidden by the "function" abstraction of the programming language.

RadcliffePikea at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 6
^good point, but do you have any suggestions on how to do this with out a method calling itself?
neolithic15a at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 7

Check out the Floyd-Warshall algorithm, and Dijkstra's algorithm (applied several times). They will have to be adapted so that the adjacency matrix is the matrix that represents whether or not there is an opening to an adjacent wall. There are some java implementations out there that can shed further light. Note, this is not a cut and paste solution. You'll have to adapt the concept to your problem (concept being the keyword).

ADJavaUsera at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 8
After some quick googling I'm afriad that is beyond the scope of my programming ability at this point. Any other suggestions?
neolithic15a at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 9
You've got the algorithm you need in your recursive solution. All you need to do is think about what information is being popped on and off the Java's stack while all these functions are being called. Then you implement your own stack and push and pop the same information on it.
RadcliffePikea at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 10

This stupid class!! He has drilled how to "think recursively" into our heads so hard that I can't think iteratively any more.I know that if I want to move to a place I should push it, but I can't think of how to keep doing this (i.e. in a loop). I've tried drawing pictues, looking at my recursive solution, but I keep getting nothing.

neolithic15a at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 11
Sounds like you need a state machine. Look up the concept and it should provide what you are looking for.
MexicoClivea at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 12
you mean an FSM?
neolithic15a at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 13
When doing at iterative solution mark your path as you back out. each path that has been marked has already been searched, so no need to follow it again.
morgalra at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 14
Well he could try an infinite state machine, but I think he wants an answer in finite time.From wiki http://c2.com/cgi/wiki?InfiniteStateMachineComputational machine whose complete description is inextricably linked to a description of the universe. For example, a flower
MexicoClivea at 2007-7-9 14:15:27 > top of Java-index,Java Essentials,Java Programming...
# 15

I think I have figured out a viable algorithm for this. I have 2 linked lists, one contains the "global" path and one contains all the legal paths thus far (a linked list of linked lists). When I find find the goal I copy the the path int to my "allPaths" list, remove the the last node and search in different directions. I do the same thing for a dead end, except I don't copy the path. For some reason I can't get it to register my global Path correctly. Here is what it looks like:

package IterativeMaze;

import Utilities.*;

import java.util.LinkedList;

/**

*

*

*/

public class iterMaze {

private LinkedList globalPath;

private LinkedList allPaths;

private int col;

private int row;

private int numRows;

private int numCols;

private int[][] grid;

public iterMaze(int numberOfCols, int numberOfRows, int[][] maze) {

col = 1;

row = 1;

grid = maze;

numRows = numberOfRows;

numCols = numberOfCols;

globalPath = new LinkedList();

allPaths = new LinkedList();

Point inital = new Point(col,row);

System.out.println("Starts at: "+col+","+row);

//if (isValid(col,row)) {

globalPath.add(inital);

//}

}

public LinkedList solve() {

while (globalPath.getFirst() != null) {

Point newPoint = new Point(col,row);

System.out.println("Current Location: "+newPoint.getCol()+","+newPoint.getRow());

if (isGoal(col,row)){

allPaths.add((Object)globalPath);

globalPath.removeLast();

}

if (isValid(col+1,row)) {// try right

Point right = new Point(row,col);

globalPath.add((Object)right);

col++;

Point top = (Point)globalPath.getFirst();

System.out.println("Right: "+col+","+row);

System.out.println("Node in path: "+top.getCol()+","+top.getRow());

}

if (isValid(col-1,row)) { //try left

Point left = new Point(col,row);

globalPath.add((Object)left);

col--;

Point top = (Point)globalPath.getFirst();

System.out.println("Left: "+col+","+row);

System.out.println("Node in path: "+top.getCol()+","+top.getRow());

}

if (isValid(col, row+1)) { //try up

Point up = new Point(col,row+1);

globalPath.add(up);

row++;

System.out.println("Up: "+col+","+row);

}

if (isValid(col,row-1)) { //try down

Point down = new Point(col,row);

globalPath.add((Object)down);

row--;

System.out.println("Down: "+col+","+row);

}

if (isDeadEnd(col,row)) {

globalPath.removeLast();

Point current = (Point)globalPath.getLast();

col = current.getCol();

row = current.getRow();

}

}

return allPaths;

}

public boolean isGoal(int col, int row) {

boolean isAtGoal = (col == numCols && row == numRows);

return isAtGoal;

}

public boolean isValid(int col,int row) {

Point aPoint = new Point(col,row);

boolean isTrue;

boolean isInGrid=(1 <= col && col < numCols && 1 <= row && row < numRows );

//System.out.println("isInGrid: "+isInGrid+" "+col+","+row);

boolean isNotPath = isNotInPath(col,row);

System.out.println("isNotPath: "+isNotPath);

boolean isNotWall = isNotAWall(col,row);

//System.out.println("isNotWall: "+isNotWall);

isTrue = (isInGrid && isNotPath && isNotWall);

//System.out.println("Point: "+col+","+row+" is "+isTrue);

return isTrue;

}

public boolean isDeadEnd(int col, int row) {

boolean isADeadEnd;

isADeadEnd = !(isValid(col+1,row)||isValid(col-1,row)||isValid(col, row+1)||isValid(col,row-1));

return isADeadEnd;

}

public boolean isNotInPath(int col, int row){

Point aPoint = new Point(col,row);

return !globalPath.contains((Object)aPoint);

}

public boolean isNotAWall(int col,int row) {

boolean notWall = true;

if (col-1>=0 && row-1>=0 && col+1 < numCols && row+1 < numRows ) {

if (grid[col-1][row-1] == 1) {notWall = false;}

}

return notWall;

}

public static void main(String[] args) {

ReadFile reader = new ReadFile();

int[][] maze = reader.read("Maze.txt");

iterMaze solver = new iterMaze(reader.getCols(),reader.getRows(),maze);

System.out.println("iterMaze");

solver.solve();

}

}

neolithic15a at 2007-7-20 4:02:11 > top of Java-index,Java Essentials,Java Programming...
# 16
My maze looks like:0 0 01 1 0It goes back and forth between 1,1 and 2,1
neolithic15a at 2007-7-20 4:02:11 > top of Java-index,Java Essentials,Java Programming...
# 17
That doesn't look too bad. I'll be honest I haven't tried it, but the main thing is if you're satisfied with it, not us.
MexicoClivea at 2007-7-20 4:02:11 > top of Java-index,Java Essentials,Java Programming...
# 18
I apologize profusely. I am very tired and didn't read your posts very well. I thought you were showing off a working program. I'll try it and get back to you. Sorry again.
MexicoClivea at 2007-7-20 4:02:11 > top of Java-index,Java Essentials,Java Programming...