import os
import time
from functools import reduce
N = 16#test case
T = [4,7,8,3,6,13,15,2,1,11,5,12,0,14,10,9,0,-1]
#obj = [4,7,8,3,6,13,15,2,1,11,5,12,14,10,0,9,0,-1]#T = [1,2,3,4,5,0,7,8,9,6,10,12,13,14,11,15,0,-1]#obj = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,-1]#obj = [4,7,8,3,6,0,15,2,1,13,5,12,14,11,10,9,0,-1]#1#obj = [4,7,8,3,1,6,15,2,13,0,5,12,14,11,10,9] #2#obj = [1,0,8,3,7,4,15,2,13,6,5,12,14,11,10,9]#3#obj = [1,4,8,3,7,6,15,2,13,5,0,12,14,11,10,9]#10#obj = [1,4,0,3,7,2,8,12,13,6,5,15,14,11,10,9]#20#obj = [1,2,4,3,7,8,0,12,13,6,5,15,14,11,10,9] #25s#obj = [1,2,0,3,7,8,4,12,13,6,5,15,14,11,10,9]#29#obj = [1,2,3,12,7,8,4,0,13,6,5,15,14,11,10,9] #31#obj = [1,2,3,12,7,8,4,15,13,6,0,5,14,11,10,9]#33#obj = [1,2,3,12,7,8,15,0,13,6,4,5,14,11,10,9] #34##obj = [1,2,15,3,7,8,4,12,13,6,0,5,14,11,10,9] #39#obj = [1,2,3,4,7,8,15,12,13,6,5,0,14,11,10,9] #45#obj = [1,2,3,4,7,8,15,0,13,6,5,12,14,11,10,9] #47#obj = [1,2,3,4,7,8,0,15,13,6,5,12,14,11,10,9]#48 #obj = [1,2,3,4,7,8,5,15,13,6,0,12,14,11,10,9]#49 #obj = [1,2,3,4,7,8,5,15,13,6,12,0,14,11,10,9] #50
obj = [1,2,3,4,5,13,6,15,14,7,11,10,0,9,8,12]#59#obj = [1,2,3,4,5,13,6,15,14,11,0,10,9,7,8,12]#the final statedefdisplacement(lhs,rhs):#compare the displacement
erro_dis = 0for i in range(len(lhs)-2):
if(lhs[i]!=rhs[i]and rhs[i]!=0):
pos1,pos2 = lhs.index(rhs[i]),rhs.index(rhs[i])
x1,x2,y1,y2 = pos1//4,pos2//4,pos1%4,pos2%4
erro_dis = erro_dis + abs(x1-x2)+ abs(y1-y2)
return erro_dis #*3 the larger the erro_dis is, the faster the search go on, with declines in the precision/accuracydefformed_print(L):
n = 0;
for i in range(0,13,4):
t = L[i:i+4]
print(t[0],t[1],t[2],t[3])
print('\n')
defget_state(node):
sum = ''for i in node[0:-2]:
sum += str(i)
return sum
defsortedinsert(path,openlist,newnode):
newnode_state = get_state(newnode)
for i,opennode in enumerate(openlist):
if(newnode[-2]+newnode[-1]<opennode[-2]+opennode[-1]):
openlist.insert(i,newnode)
return
openlist.append(newnode)
deffind_next_nodes(curr_node):defswap(L,i,j):#return a list with swapped items
temp = L[::]
temp[i],temp[j] = temp[j],temp[i]
return temp
pos = curr_node.index(0)#find the position of 0
i,j = pos//4,pos%4#convert pos to grid coordinates
nextnodes = []
if(i!=3):nextnodes.append(swap(curr_node,pos,pos+4))
if(i!=0):nextnodes.append(swap(curr_node,pos,pos-4))
if(j!=3):nextnodes.append(swap(curr_node,pos,pos+1))
if(j!=0):nextnodes.append(swap(curr_node,pos,pos-1))
return pos,nextnodes
deffind_same_node(openlist,it):for node in openlist:
if(node[:-2]==it[:-2]):
return node
defbfs():
path = {}
iscompleted = False
openlist = []#the statelist
openlist.append(T)#add the first node
visit = {}#use visit to indicate being visited
wait_visited ={}
visit[get_state(T)] = 1;
wait_visited[get_state(T)] = True#indicate the node that wait to be visited
path[get_state(T)] = [-1,0]#four arguments means the (1)parent state,(2)pos of zero,(3)depth of node,(4)the evaluation of nodewhile(len(openlist)!=0):#if the open list is empty,loop ends
curr_node = openlist[0]
state = get_state(curr_node)
openlist.remove(curr_node)
wait_visited[state] = False#meaning the node are visitedif(curr_node[:-2] == obj):#if the obj is found,break the loopreturn path,curr_node,curr_node.index(0),state
zero_pos,nextnodes = find_next_nodes(curr_node)#return all nodes near to 0 and pos of 0for node in nextnodes:
next_state = get_state(node)
if(not(next_state in visit)):#the node is not visited and not waitting to be visited
visit[next_state] = 1
wait_visited[next_state] = True
path[next_state] = [state,zero_pos]#record the state path and the solution
node[-2],node[-1] = curr_node[-2]+1,displacement(node,obj)
openlist.append(node)
sortedinsert(path,openlist,node)#insert the node in approriate positionelif(wait_visited[next_state]== True):#meaning the node is waitting to be visited
samenode = find_same_node(openlist,node)
if(curr_node[-2]+1+displacement(node,obj)<samenode[-2]+samenode[-1]):#the new node is better
node[-2],node[-1] = curr_node[-2]+1,displacement(node,obj)
sortedinsert(path,openlist,node)
#add the node which estimation is lessreturnFalsedefmove(path,zero_pos,state):
zero_list = [zero_pos]
while(path[state][0]!=-1):
zero_list = [path[state][1]]+zero_list
state = path[state][0]
print('steps:',len(zero_list))
time.sleep(3)# display the stepsfor i in range(len(zero_list)-1):
os.system('cls')
formed_print(T)
time.sleep(0.1)
T[zero_list[i]],T[zero_list[i+1]] = T[zero_list[i+1]],T[zero_list[i]]
os.system('cls')
formed_print(T)
print(get_state(T))
path,node,zero_pos,state = bfs()
move(path,zero_pos,state)