views:

512

answers:

8

A rat is placed in a maze at some unknown position in the maze.

All we can go is in up, down, right or left directions. And we have two methods:

  • tryMove(<direction>) which returns false if there is a wall and true if we can move.
  • bool hasLadder(): which returns true if there is a ladder to escape.

We have to write a function explore which returns true if we find the way out or false if there is no way.

This is a simple graph problem and can be solved using bfs or a dfs algorithm if we can find mark these places. If we cannot mark these places we can move in cycles visiting the same places. Can some one help me to get rat out of the maze please if its unmarked? Is it possible?

A: 

You should run BFS algorithms. The only problem I see is how to define graph. It can be defined with von Neumann neighborhood. Node is defined as X,Y pair. Pseudo code should look like:

BFS
while (!Q.empty()){
    v = Q.top()
    neighbours = get_adj_list(v)
    foreach (w in neighbours){
        if (isWall(w) || isOutsideMaze(w)) skip
        if (isTerminal(w)) printPathAndExit
        if (dist[v] + 1 < dist[w])
            dist[w] = dist[v] + 1
            Q.push(w)
    }
}

GEN_NEIGHBOURS
dx = {-1,1}
dy = {-1,1}

get_adj_list(v)
    adj_list = []
    for (i in dx)
        for (j in dy)
            adj_list << node(v.x-i,v.y-j)
    return adj_list

EDIT: now I read the memory limit is O(1). So I guess you should follow old method to always turn to the right and you will eventually get out of the maze or get back to start position.

EDIT2: from Corn Maze tips:

As with any maze, if consistently take either the right or left hand turns, you will eventually find a way out. Running your finger long the wall of the maze without lifting it will keep you on the right track.

jethro
LOL try to make the rat tiered?
Eiko
The OP said that you don't have the ability to mark a node as visited, though, which implies you don't have the ability to "remember" the distance to get to a node, either.
Dean J
@Dean: Please read edit notes
jethro
The left-hand-on-wall rule only works for simply connected mazes, which this may not be. Imagine a maze with walls around the outside, a clear path around a patch of walls, and a ladder in the patch. A rat in the outer area won't find the ladder with left-paw-on-wall.
David Thornley
@David Thornley you are right it works only for some specific class of mazes that can be called classsic mazes.
jethro
The "hand on wall" algorithm becomes completely general if you add the rule "switch to the other wall anytime you come back to a place you've been before". Basically, anytime you loop around you've explored all of one side of the path you are on, so now try the other side. Of course, that means either remembering where you've been, or coloring your path.
dmckee
+11  A: 

Both breadth-first and depth first search require memory and a naive algorithm can loop indefinitely. A rat probably only has O(1) memory.

One way to solve it without remembering where you have been is to pick a direction at random. The solve time will be extremely long, but it should eventually reach every reachable square. This is related to the 2D random walk.

Amazingly, it has been proven that on a two-dimensional lattice, a random walk has unity probability of reaching any point (including the starting point) as the number of steps approaches infinity.

Mark Byers
Unfortunately, the random walk strategy will not allow us to return false if exit is not possible, a part of OP's homework.
Adam Crossland
@Adam Crossland if(time > infinity) return false;
James
That answer will definitely get him a job at Microsoft.
Adam Crossland
@Mark Byers, since you have no idea of the size of the maze, you cannot even make an estimation...
James
@James: Perhaps my computer is defective, but it can only count up to "infinity - 1".
Steven Sudit
@Steven Sudit When was the last time you tried? Mine's still counting.
James
@James: Good point if you don't know the size of the maze... but the OP didn't specify whether or not you know the size of the maze, only that your initial position in the maze is unknown. *If* you know the size of the maze then you can probably make a reasonable estimate.
Mark Byers
@James: Nope, mine stops on "infinity - 1" on the dot, quite consistently. Thanks to quad cores with hyperthreading, it's almost 5x faster at a near-infinite loop than a single-core machine at the same clock speed.
Steven Sudit
«A rat probably only has O(1) memory.» Somehow I doubt that.
ninjalj
@ninjalj: Why do you doubt it? It seems an entirely reasonable assumption to me. The idea that a rat's memory capacity would depend on the size of the maze it is placed in seems very unlikely.
Mark Byers
Of course a hypothetical spherical rat on a vacuum may have O(1) memory, but I seriously doubt a real life rat would use its memory the same way on different mazes.
ninjalj
I don't know about O(1) memory, but I've seen rats solve probability problems better than a class full of psychology students. (No, seriously)
Brian S
@Brian: This says much about psychology students, but little about rats.
Steven Sudit
@ninjalj: but its memory capacity is still fixed. It doesn't grow new brain cells depending on the size of the maze.
jalf
The rats memory (as well as being O(1)) probably isn't very big either so any solutions will have to be small to ensure they fit
Daniel
A: 

This is a classic problem often used as a homework assignment.

Try this:

  1. Can you tell if you are at the way out right now?
  2. Once you have that, what do you need to do to find out if you are within one move of the way out?
  3. How about if you are within 2 moves of the way out?

...

As Mark notes, the simplest versions of the algorithm I'm trying to lead you to can get locked in a loop. How can you solve this problem?

dmckee
This looks an awful lot like Korf's Iterative Deepening search. BTW, loops themselves will only be inefficient. Only worry if you're locked into one.
David Thornley
@David: I hadn't know that this had a name. [Mr. Korf's paper (PDF link)](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.288) is very interesting. I particularly like the use of working Rubik's cube solutions on a VAX 11/780 as an example.
dmckee
A: 

If I remember correctly, I had a recursion homework assignment like this a long time ago, however it wasn't limited to O(1) memory. We just couldn't build 'maps' of where we've been and had to use recursion... I guess this would use O(n) memory, where n is the shortest distance to the ladder from the start.

while( 1 )
    {
    if( search( MOVE_LEFT, i ) ||
        search( MOVE_UP, i ) ||
        search( MOVE_RIGHT, i ) ||
        search( MOVE_DOWN, i ) )
         {
         return TRUE;
         }
    i++;
    }

/* recursive function */
bool search( move_type move, long int length )
{

doMove( move ); /* actually move the rat to requested place */

if( hasLadder() )
    return TRUE;

if( 0 == length )
    return FALSE;

switch( move ) /* check each and return rat to previous place */
    {
    case MOVE_LEFT:  
        if( tryMove( MOVE_LEFT ) && search( MOVE_LEFT, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_UP ) && search( MOVE_UP, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_DOWN ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE;      
        doMove( MOVE_RIGHT ); break;
    case MOVE_UP:
        if( tryMove( MOVE_LEFT ) && search( MOVE_LEFT, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_UP ) && search( MOVE_UP, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_RIGHT ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE; 
        doMove( MOVE_DOWN ); break;
    case MOVE_RIGHT:
        if( tryMove( MOVE_UP ) && search( MOVE_UP, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_RIGHT ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_DOWN ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE;      
        doMove( MOVE_LEFT ); break;
    case MOVE_DOWN:
        if( tryMove( MOVE_LEFT ) && search( MOVE_LEFT, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_RIGHT ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE;
        if( tryMove( MOVE_DOWN ) && search( MOVE_RIGHT, length - 1 ) ) return TRUE;      
        doMove( MOVE_UP ); break;
    }

return FALSE;

}   /* search() */
ritalinkid18
A: 

Determining whether there is a way out sounds a lot like a halting problem to me. It can be solved for all trivial and many non trivial cases but for lots of maps unless you can mark where you have been you can't prove that the map isn't infinite.

http://en.wikipedia.org/wiki/Halting_problem

Daniel
Care to explain the downvote?
Daniel
+1  A: 

With no memory the only solution is the random one and it's terrible. If you know the maze is only singly connected you can use a wall-following approach but that can go into an infinite loop if the maze contains a loop.

Loren Pechtel
+2  A: 

The algorithm is basically USTCON (undirected st-connectivity): given an undirected graph G, determine if there is a path from node s (the rat's start position) to node t (the exit). This problem is in complexity class L, which means it requires a logarithmic amount of memory. So, unless you have an upper bound on the size of the maze, or are willing to approximate, it is impossible with constant space.

Cirno de Bergerac
According to the paper Omer Reingold has an O(log n) algorithm: http://portal.acm.org/citation.cfm?id=1060647
Mark Byers
A: 

Funny that @mousey would ask about a rat... anwyay.

I have seen this problem creep up a number of times already.

The first (and naive) solution is to follow the left (or right) wall, however it's possible to craft specific mazes where the rat end up running in circles.

In fact, for every deterministic order of moves (like 2L, 1R, 2L, 1R, ...) that I tried (being in high school I had time) we could come up with a maze that would make the rat run in circles. Of course, the more complicated the cycle, the more complicated the maze.

Therefore, if you have O(1) memory, the only solution to get out of the maze seems to be a random walk, as proposed by Mark Byers. Unfortunately you cannot prove it's impossible to get out of the maze with such an algorithm.

On the other hand, if you have O(N) memory, it boils down to creating a map (somehow). The strategy I finally come up with back then was to leave pheromon (incrementing a counter) on each case I passed, and when having a choice in a move, to choose among the least visited cases. However it was always possible to get out so I never had to think about a termination condition in case there is no exit.

You can also use a flood fill algorithm...Of course, it was before I learned about the term BFS. This has the advantage that you do have a termination condition (when there isn't any case left to explore).

Matthieu M.