Skip to content

Commit

Permalink
Add NPuzzle with DFS/IDFS algos
Browse files Browse the repository at this point in the history
  • Loading branch information
nsauzede committed Jan 5, 2024
1 parent 430ca20 commit 8b9c48d
Showing 1 changed file with 227 additions and 0 deletions.
227 changes: 227 additions & 0 deletions vade/src/NPuzzle/_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import unittest
from copy import deepcopy
def gen(inp:list)->list:
a,b,c,d=[deepcopy(inp)for i in range(4)]
if inp[0][0]==0:
a[0][0],a[0][1]=a[0][1],a[0][0]
b[0][0],b[1][0]=b[1][0],b[0][0]
l=[a,b]
elif inp[0][1]==0:
a[0][1],a[0][0]=a[0][0],a[0][1]
b[0][1],b[0][2]=b[0][2],b[0][1]
c[0][1],c[1][1]=c[1][1],c[0][1]
l=[a,b,c]
elif inp[0][2]==0:
a[0][2],a[0][1]=a[0][1],a[0][2]
b[0][2],b[1][2]=b[1][2],b[0][2]
l=[a,b]
elif inp[1][0]==0:
a[1][0],a[1][1]=a[1][1],a[1][0]
b[1][0],b[0][0]=b[0][0],b[1][0]
c[1][0],c[2][0]=c[2][0],c[1][0]
l=[a,b,c]
elif inp[1][1]==0:
a[1][1],a[1][0]=a[1][0],a[1][1]
b[1][1],b[1][2]=b[1][2],b[1][1]
c[1][1],c[0][1]=c[0][1],c[1][1]
d[1][1],d[2][1]=d[2][1],d[1][1]
l=[a,b,c,d]
elif inp[1][2]==0:
a[1][2],a[1][1]=a[1][1],a[1][2]
b[1][2],b[0][2]=b[0][2],b[1][2]
c[1][2],c[2][2]=c[2][2],c[1][2]
l=[a,b,c]
elif inp[2][0]==0:
a[2][0],a[2][1]=a[2][1],a[2][0]
b[2][0],b[1][0]=b[1][0],b[2][0]
l=[a,b]
elif inp[2][1]==0:
a[2][1],a[2][0]=a[2][0],a[2][1]
b[2][1],b[2][2]=b[2][2],b[2][1]
c[2][1],c[1][1]=c[1][1],c[2][1]
l=[a,b,c]
elif inp[2][2]==0:
a[2][2],a[2][1]=a[2][1],a[2][2]
b[2][2],b[1][2]=b[1][2],b[2][2]
l=[a,b]
return l
def disp_valid(l:list,last):
for e in l:
valid=e!=last
#print(f" {e},{'OP'if valid else'cl'}",end="")
#print()
def get_next(l:list,last=None)->list:
#print(f"finding first non {last}")
for e in reversed(l):
if e!=last:
return e
0/0

def dfs(inp0:list, goal:list)->int:
seen={}
#print()
return dfs_walk(inp0,goal, seen)

def dfs_walk(inp0:list, goal:list, seen:dict, step=0)->int:
#print(f"step={step} inp0={inp0} seen={seen}")
#print(f"step={step} inp0={inp0} seen={len(seen)}")
if inp0==goal:
#print(f"found goal! seen={len(seen)}")
return step
sinp0=str(inp0)
if sinp0 in seen:
#print("already seen!")
return 0
seen[sinp0]=1
out=gen(inp0)
for inp in reversed(out):
#print(f"step={step} walking inp={inp} seen={seen}")
#print(f"step={step} walking inp={inp} seen={len(seen)}")
res=dfs_walk(inp, goal, seen, step+1)
if res>0:
#print(f"child found returned res={res}")
return res
#print("first try failed")
#0/0
#0/0
return 0

def idfs_walk(inp0:list, goal:list, seen:dict, depth:int, step=0)->int:
if step>depth:
#print("too many steps!")
return 0
#print(f"step={step} depth={depth} inp0={inp0} seen={len(seen)}")
if inp0==goal:
#print(f"found goal! seen={len(seen)}")
return step
sinp0=str(inp0)
if sinp0 in seen:
#print("already seen!")
return 0
seen[sinp0]=1
out=gen(inp0)
for inp in reversed(out):
#print(f"step={step} walking inp={inp} seen={seen}")
#print(f"step={step} walking inp={inp} seen={len(seen)}")
res=idfs_walk(inp, goal, seen, depth, step+1)
if res>0:
#print(f"child found returned res={res}")
return res
#print("first try failed")
#0/0
#0/0
return 0

def idfs(inp0:list, goal:list)->int:
depth=0
res=0
print()
while True:
seen={}
res = idfs_walk(inp0, goal, seen, depth)
if res>0:
#print(f"found res={res} at depth={depth}")
break
depth+=1
return res

class T000(unittest.TestCase):
def test_idfs_0000(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[1,2,3],[4,5,6],[8,7,0]]
res=idfs(init, goal)
self.assertEqual(4, res)
def test_dfs_0004(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[1,2,3],[8,0,4],[7,6,5]]
res=dfs(init, goal)
self.assertEqual(32, res)
def test_dfs_0003(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[1,2,3],[8,4,5],[7,0,6]]
res=dfs(init, goal)
self.assertEqual(3, res)
def test_dfs_0002(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[1,2,3],[8,4,5],[0,7,6]]
res=dfs(init, goal)
self.assertEqual(2, res)
def test_dfs_0001(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[1,2,3],[0,4,5],[8,7,6]]
res=dfs(init, goal)
self.assertEqual(1, res)
def test_dfs_0000(self):
init=[[0,2,3],[1,4,5],[8,7,6]]
goal=[[0,2,3],[1,4,5],[8,7,6]]
res=dfs(init, goal)
self.assertEqual(0, res)
def test_0000(self):
#print()
inp,out,last=[],[],None
# initial input as previous output
out+=[[ [[0,2,3],[1,4,5],[8,7,6]]]]
# expected output reference
outr=[ [[2,0,3],[1,4,5],[8,7,6]],
[[1,2,3],[0,4,5],[8,7,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])

outr=[ [[1,2,3],[4,0,5],[8,7,6]],
[[0,2,3],[1,4,5],[8,7,6]],
[[1,2,3],[8,4,5],[0,7,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])
self.assertEqual(out[0][0],out[2][1])

outr=[ [[1,2,3],[8,4,5],[7,0,6]],
[[1,2,3],[0,4,5],[8,7,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])
self.assertEqual(out[1][1],out[3][1])

outr=[ [[1,2,3],[8,4,5],[0,7,6]],
[[1,2,3],[8,4,5],[7,6,0]],
[[1,2,3],[8,0,5],[7,4,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])

outr=[ [[1,2,3],[0,8,5],[7,4,6]],
[[1,2,3],[8,5,0],[7,4,6]],
[[1,0,3],[8,2,5],[7,4,6]],
[[1,2,3],[8,4,5],[7,0,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])
self.assertEqual(out[3][0],out[5][3])

outr=[ [[0,1,3],[8,2,5],[7,4,6]],
[[1,3,0],[8,2,5],[7,4,6]],
[[1,2,3],[8,0,5],[7,4,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])
self.assertEqual(out[4][2],out[6][2])

outr=[ [[1,0,3],[8,2,5],[7,4,6]],
[[1,3,5],[8,2,0],[7,4,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])

outr=[ [[1,3,5],[8,0,2],[7,4,6]],
[[1,3,0],[8,2,5],[7,4,6]],
[[1,3,5],[8,2,6],[7,4,0]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])

outr=[ [[1,3,5],[8,2,6],[7,0,4]],
[[1,3,5],[8,2,0],[7,4,6]],]
inp+=[get_next(out[-1],last)];last=inp[-2]if len(inp)>1 else[]
out+=[gen(inp[-1])];disp_valid(out[-1],last)
self.assertEqual(outr,out[-1])

0 comments on commit 8b9c48d

Please sign in to comment.