Newsgroups: comp.ai,comp.ai.edu,comp.ai.games,comp.ai.genetic
Path: cantaloupe.srv.cs.cmu.edu!rochester!cornellcs!newsstand.cit.cornell.edu!portc01.blue.aol.com!news-peer.gsl.net!news.gsl.net!howland.erols.net!feed1.news.erols.com!arclight.uoregon.edu!news.bc.net!unixg.ubc.ca!noc.van.hookup.net!vertex.tor.hookup.net!loki.tor.hookup.net!omega.metrics.com!news.maplesoft.on.ca!news
From: Terry Van Belle <vanbelle@maplesoft.com>
Subject: Re: Rubik's Cube
Content-Type: text/plain; charset=us-ascii
Message-ID: <32823109.1B8A@maplesoft.com>
Sender: news@maplesoft.on.ca (News File Owner)
Nntp-Posting-Host: agate
Content-Transfer-Encoding: 7bit
Organization: Waterloo Maple Inc.
References: <01bbcaab$dff4c780$b16c60cf@erols.com.erols.com>
Mime-Version: 1.0
Date: Thu, 7 Nov 1996 18:57:13 GMT
X-Mailer: Mozilla 2.01Gold (WinNT; U)
Lines: 72
Xref: glinda.oz.cs.cmu.edu comp.ai:41968 comp.ai.edu:3764 comp.ai.games:6904 comp.ai.genetic:10275

Gabor Fenyes wrote:
> Thank you very much!  In addition, I have received numerous emails of help
> [a sea of thanks to everyone!], and I'd just like to clarify a few details
> of what type of solution algorithm I'm looking for:
> 
> A strictly recursive one (if it exists).  This is of the type where a
> single function calls itself.  I was thinking that the stopping case would
> be when the cube is complete, else call the same function with all the
> possible movements (18) one can do from a position.  This did not work
> because all the function does is it keeps doing the same move forever,
> until the memory stack is full.  I even tried passing the function the
> movement that has been done before, but that didn't quite work out either.
> 
> Some of my questions, then:  Should I change the possible number of
> movements (18)?  Remember 18 is gotten by being able to do a 90,180, and
> 270 degree rotation on each face of the cube, so 6*3 = 18...  Perhaps just
> have 6 possible movements (90 degree for each side)?  Or 12 by using the
> fact that 90+180=270?  Is the solution doable in each of these cases?

Take a cue from the computer game playing folks, who have been doing this sort
of thing on game trees forever.  First of all, any sort of naive recursion
is going to pretty quickly slam against the exponential explosion of possible
states.  With 18 possible moves each turn, the number of states you need to
check for n moves is 18^n.  A little arithmetic gives us
    18^5  = 1,889,568
    18^10 = 3,570,467,226,624
    18^15 = 6,746,640,616,477,458,432
    18^20 = 12,748,236,216,396,078,174,437,376

On the other hand, there are many paths to the same state, so I'd build a hash
table and store the states, along with the depth you searched from them in the
table.  Then you search to depth=1, depth=2, depth=3, etc... until you either
find a solution or get bored.

Pseudocode would go along these lines:

// hash[S].depth is the depth we've searched from S without finding a solution

// search() returns TRUE if there is a solution reachable from S within depth
// moves.
boolean search( State S, int depth )
{
    if( depth == -1 )
        return FALSE

    if( solved(S) ) {
        print some sort of history of how we got here
        return TRUE
    }

    if( S is in hash and hash[S].depth >= depth )
        return FALSE

    for( newS = each new state reachable from S ) {
        if( search( newS, depth-1 ) )
            return TRUE
    }

    // not found at this depth.  record the fact in the hash table
    hash[S].depth = depth

    return FALSE
}

for( depth = 0 to infinity )
    if( search( initialS, depth ) )
        break

I've probably messed up some of the details, but that's the general idea.
Good luck!

Terry
