SJS wrote:
I as at a friend's place over the holidays, and I picked up a little sliding-tile puzzle of a lizard. There were 8 pieces on a little 3x3 grid, and I futzed with it a bit and decided that I didn't even like those sorts of puzzles when they were that small.

That night, the cat got up in my lap, arranged itself across my forearms, so I decided to "solve" the 3x3 8-piece sliding tile puzzle. Now, this would have been an ideal time to try out Ruby, but
 with a purring cat trapping my arms, that wasn't really practical.

Same with perl or TCL... I'd need a reference book at hand, and that wasn't going to happen unless I dumped the cat. And it's just wrong to dump a purring cat, so I fell back on that old standby we call C.

Funny.  I wouldn't be able to pull that C out without grabbing at K&R.

However, my Python, even after not having written it for probably about
1 1/2 years is *still* just fine.  I think you are far more clever than
I in choice of algorithm.  I just used a simple recursive descent and
used a hash table to remember what states I already visited.

What is interesting to me is the difference in lines of code.  Not
because Python is so much better, but simply because I could use vectors,
hash tables, strings, and sequences directly and Stewart had to reimplement
a data structure (deque).

And this matches my philosophy very well.  I *HATE* reimplementing data
structures that already exist.

-a


After about 80 minutes of coding I have:

#!env python

import sys
import copy

availableDirs = [[(1, 0), (0, 1)], [(-1, 0), (0, 1), (1, 0)], [(-1, 0), (0, 1)],
                [(0, -1), (1, 0), (0, 1)], [(-1, 0), (0, -1), (1, 0), (0, 1)], 
[(0, -1), (-1, 0), (0, 1)],
                [(1, 0), (0, -1)], [(-1, 0), (0, -1), (1, 0)], [(-1, 0), (0, 
-1)]]

def swapSpace(puzzleState, direction):
   spacePosition = puzzleState.find(" ")

   spaceI = spacePosition % 3
   spaceJ = spacePosition / 3

   coordI = spaceI + direction[0]
   coordJ = spaceJ + direction[1]

   coordPosition = coordI + coordJ*3

   newStateList = []
   for ii in range(len(puzzleState)):
       if ii == spacePosition:
           newStateList.append(puzzleState[coordPosition])
       elif ii == coordPosition:
           # Redundant, should just use space
           newStateList.append(puzzleState[spacePosition])
       else:
           newStateList.append(puzzleState[ii])

   newState = "".join(newStateList)

   return newState

def solveSingleStep(solutionState, targetState, visitedSolutions):
   flgSolutionFound = False
   nextSolutionState = []
   solution = None

   for (previousSteps, puzzleState) in solutionState:
       nextDirs = availableDirs[puzzleState.find(" ")]

       visitedSolutions[puzzleState] = True

       for testDir in nextDirs:
           newState = swapSpace(puzzleState, testDir)

           newPreviousSteps = copy.copy(previousSteps)
           newPreviousSteps.append(testDir)

           if newState == targetState:
               flgSolutionFound = True
               solution = (newPreviousSteps, newState)
               break
           elif newState in visitedSolutions:
               # New solution has already been visited ... ignore
               pass
           else:
               nextSolutionState.append((newPreviousSteps, newState))

       if flgSolutionFound:
           break

   if flgSolutionFound:
       return (True, solution)
   else:
       return (False, nextSolutionState)

def boardPPrint(currentState):
   ll = []
   for ii in currentState:
       ll.append(ii)
   ll = tuple(ll)

   print "[%s] [%s] [%s]\n[%s] [%s] [%s]\n[%s] [%s] [%s]\n\n" % ll

def main():
   if len(sys.argv) != 3:
       print "Wrong number of arguments"
       exit()

   startingState = sys.argv[1]
   targetState = sys.argv[2]

   flgSolved = False
   solutionState = [([], startingState)]
   visitedSolutions = {}

   while(not flgSolved):
       (flgSolved, newSolutionState) = solveSingleStep(solutionState, 
targetState, visitedSolutions)
       solutionState = newSolutionState

       print "NSS:", len(newSolutionState), len(visitedSolutions)


   if flgSolved:
       print "SOLVED in %d steps: %s" % (len(solutionState[0]), 
str(solutionState))

   currentState = startingState
   for ss in solutionState[0]:
       boardPPrint(currentState)
       currentState = swapSpace(currentState, ss)
   boardPPrint(currentState)
if __name__ == "__main__":
   main()



andrewl$ time python puzzle3.py "12345678 " " 87654321"
NSS: 2 1
NSS: 4 3
NSS: 8 7
NSS: 16 15
NSS: 20 31
NSS: 40 51
NSS: 66 90
NSS: 128 152
NSS: 164 268
NSS: 316 420
NSS: 456 706
NSS: 862 1102
NSS: 1206 1850
NSS: 2260 2874
NSS: 3162 4767
NSS: 5836 7279
NSS: 7760 11764
NSS: 13920 17402
NSS: 17344 26931
NSS: 29282 37809
NSS: 33280 54802
NSS: 51332 71912
NSS: 52140 95864
NSS: 71268 116088
NSS: 58492 140135
NSS: 65554 155713
NSS: 39710 170273
NSS: 2 171445
SOLVED in 28 steps: ([(-1, 0), (-1, 0), (0, -1), (0, -1), (1, 0), (1, 0), (0, 
1), (0, 1), (-1, 0), (-1, 0), (0, -1), (0, -1), (1, 0), (1, 0), (0, 1), (0, 1), 
(-1, 0), (-1, 0), (0, -1), (0, -1), (1, 0), (1, 0), (0, 1), (0, 1), (-1, 0), 
(-1, 0), (0, -1), (0, -1)], ' 87654321')
[1] [2] [3]
[4] [5] [6]
[7] [8] [ ]


[1] [2] [3]
[4] [5] [6]
[7] [ ] [8]


[1] [2] [3]
[4] [5] [6]
[ ] [7] [8]


[1] [2] [3]
[ ] [5] [6]
[4] [7] [8]


[ ] [2] [3]
[1] [5] [6]
[4] [7] [8]


[2] [ ] [3]
[1] [5] [6]
[4] [7] [8]


[2] [3] [ ]
[1] [5] [6]
[4] [7] [8]


[2] [3] [6]
[1] [5] [ ]
[4] [7] [8]


[2] [3] [6]
[1] [5] [8]
[4] [7] [ ]


[2] [3] [6]
[1] [5] [8]
[4] [ ] [7]


[2] [3] [6]
[1] [5] [8]
[ ] [4] [7]


[2] [3] [6]
[ ] [5] [8]
[1] [4] [7]


[ ] [3] [6]
[2] [5] [8]
[1] [4] [7]


[3] [ ] [6]
[2] [5] [8]
[1] [4] [7]


[3] [6] [ ]
[2] [5] [8]
[1] [4] [7]


[3] [6] [8]
[2] [5] [ ]
[1] [4] [7]


[3] [6] [8]
[2] [5] [7]
[1] [4] [ ]


[3] [6] [8]
[2] [5] [7]
[1] [ ] [4]


[3] [6] [8]
[2] [5] [7]
[ ] [1] [4]


[3] [6] [8]
[ ] [5] [7]
[2] [1] [4]


[ ] [6] [8]
[3] [5] [7]
[2] [1] [4]


[6] [ ] [8]
[3] [5] [7]
[2] [1] [4]


[6] [8] [ ]
[3] [5] [7]
[2] [1] [4]


[6] [8] [7]
[3] [5] [ ]
[2] [1] [4]


[6] [8] [7]
[3] [5] [4]
[2] [1] [ ]


[6] [8] [7]
[3] [5] [4]
[2] [ ] [1]


[6] [8] [7]
[3] [5] [4]
[ ] [2] [1]


[6] [8] [7]
[ ] [5] [4]
[3] [2] [1]


[ ] [8] [7]
[6] [5] [4]
[3] [2] [1]



real    0m15.413s
user    0m15.181s
sys     0m0.160s

Time is in a 2.16GHz core 2 duo

--
[email protected]
http://www.kernel-panic.org/cgi-bin/mailman/listinfo/kplug-lpsg

Reply via email to