Jiugong jigsaw puzzle

Keywords: Python

problem

In the space of 3*3, the numbers of 1-9 are placed respectively, and then one of them is set to zero as the space, disrupting the order, requiring the least steps back to the original form.

thinking

This problem can be solved by breadth-first search.
Firstly, the number distribution can be as many as 987654321 = 362880. We set up a two-dimensional list of 9 * 362880 to store an array representing the number distribution of nine palaces. Then move the spaces in all directions and create another list to store the number of times you move to a certain number distribution until you get back to where you were.

Looking at the other codes on the internet, we can only calculate the minimum number of times, not show how to move each step. Here I use a list as a precursor to record which step I got from, and finally just bring it in. If there are other ways to communicate, please.

Code

Here I'm writing in python, where li0 is the disrupted nine-palace, and li_goal is the restored form.

def bool_rules(first,next):
    """Judgment of legality of movement 1-9"""
    if (first>9)|(first<1)|(next>9)|(next<1):
        return 0
    elif (first%3==0)&(next%3==1):
        return 0
    elif (first%3==1)&(next%3==0):
        return 0
    elif ((abs(first-next)==3)|(abs(first-next)==1)):
        return 1
    else:
        return 0

def turn(x,y,li):
    #1-9
    #Swap positions, return the positions of arrays and spaces
    temp = li[:]
    temp[x-1] = li[y-1]
    temp[y-1] = li[x-1]
    return temp

def insert_exist(s):
    v = 0
    for i in range(0,9):
        v = v*10 + st[s][i]
    if vis.count(v)>0:
        return 0
    else:
        vis.append(v)
        return 1

def cmp(q,p):#The difference is 1, the same is 0.
    if len(q)-len(p)!=0:
        return 1
    x=0
    for i in range(0,len(q)):
        if q[i]!=p[i]:
            return 1
    return 0

def run():
    st[1]=li0[:]
    front = 1
    rear = 2
    while front<rear:
        if cmp(st[front],li_goal)==0:
            return front
        x=st[front].index(0)+1
        for i in move:
            if bool_rules(x, x + i):
                st[rear]=turn(x,x+i,st[front][:])[:]
                if insert_exist(rear):
                    dist[rear] = dist[front]+ 1
                    before[rear]=front
                    rear +=1
        front+=1
    return -1



if __name__ == '__main__':
    li_goal = list(range(1, 10))
    global move  # Up and down
    move = [-3, 3, -1, 1]
    max = 362880  # 9*8*7*6*5*4*3*2*1
    st = [[0 for i in range(9)] for i in range(max)]
    vis = [0]
    dist = [0 for i in range(max)]
    before = [0 for i in range(max)]
    li0=[1,2,3,0,6,9,4,7,8]
    li_goal[5-1]=0


    a=run()
    num=dist[a]
    print('frequency:',num)
    step = [[0 for i in range(9)] for i in range(num+1)]
    step[num]=li_goal[:]
    for i in range(1,num+1):
        b=before[a]
        step[num - i]=st[b][:]
        a=b
    for i in range(0,num+1):
        print('step ',i)
        print(step[i][0:3])
        print(step[i][3:6])
        print(step[i][6:9])

Result

Posted by webv on Tue, 16 Apr 2019 17:21:33 -0700