# Python experiment — handwritten a * algorithm to realize eight digital problems

Time：2022-1-23

## 1. Problem description

For problem: Path Search

Problem Description: A, B, C N nodes, each node has defined whether it can reach and path cost, and the goal is to search the best path

Eight digit problem: there are 1-8 eight numbers in the 3 * 3 Jiugong grid, and the remaining one is a space. You can only move the space once at a time. Given the initial state and target state, you can find the best moving method and the shortest moving distance

## 2. Principle of a algorithm

1. First, put the initial node into the open table
2. Put the initial node into the closed table, expand the node in all directions from the initial node, and put the new extended node into the open table
3. The cost is calculated according to the path corresponding to the new extension node, and then sorted
4. Select the node with the lowest cost from the open table as the current node and put it into the closed table
5. Repeat steps 2 and 3.4 until the target node is found and the best path is returned

## 3. A * algorithm requirements

The difference between a * algorithm and a algorithm lies in the requirements for the formula of path calculation cost

Algorithm A: cost = historical cost + future cost (heuristic function), where historical cost refers to the known cost of walking to the current state, and future cost refers to the estimated cost from the current node to the target state

A * algorithm: the estimated cost must be greater than or equal to the real future cost

## 4. How to judge whether there is an reachable path between given states

The concept of reverse order number is introduced: in an arrangement, if the front and rear positions of a logarithm are opposite to the size order, that is, the front number is greater than the rear number, then they are called a logarithmReverse order。 The total number in reverse order in an arrangement is called the total number of the arrangementReverse order number

After calculating the reverse order numbers of the initial state and the target state, if the parity of the two states is consistent, they can be reached, otherwise, they cannot be reached

## 5.1. Subfunction definition

### 5.1.1. Reverse order number calculation

def judge(number):
total = 0
data = [9, 9, 9, 9, 9, 9, 9, 9, 9]
for i in range(9):
if number[i] != '0':
data[i] = int(number[i])
else:
data[i] = 0
for i in range(9):
for j in range(i):
if data[i] * data[j] != 0:
if data[j] > data[i]:
total = total + 1

## 5.1.2. Adjust node location based on cost

if len(open) == 0 or node[2] >= open[-1][2]:
open.append(node)
else:
for i in range(len(open)):
if node[2] < open[i][2]:
open.insert(i, node)
break

### 5.1.3. Heuristic function (Manhattan distance)

def manhattan(src, dst):
total = 0
pos_src = [[0 for x in range(2)] for y in range(9)]
pos_dst = [[0 for x in range(2)] for y in range(9)]
for i in range(9):
x = i // 3
y = i % 3
pos_src[int(dst[i])][0] = x
pos_src[int(dst[i])][1] = y
pos_dst[int(src[i])][0] = x
pos_dst[int(src[i])][1] = y
for i in range(9):
total = total + abs(pos_src[i][0]-pos_dst[i][0]) + abs(pos_src[i][1]-pos_dst[i][1])

### 5.1.4. Returns the position of 0 in the sequence

def position(src):
flag = src.index('0')
row = int(flag // 3)
col = int(flag % 3)
return [flag, row, col]

### 5.1.5. change of position

def exchange(src, x, y, x2, y2):
flag = x * 3 + y
flag2 = x2 * 3 + y2
tmp1 = src[flag]
tmp2 = src[flag2]
dst = copy.copy(src)
dst[flag] = tmp2
dst[flag2] = tmp1
return dst

5.1.6. Print node status

def prtNum(src):
for x in range(3):
for y in range(3):
print(str(src[x * 3 + y] + ' '), end='')
print()

## 5.2. Extended node function

Information carried by each node in the table:

[this node description, parent node code, this node cost, this node code, whether it is in target status]

def expand(src, side):
global crt
global nodeid
pos = position(src)
x = pos[1]
y = pos[2]
rtResult = []

#Calculate the historical cost of a node (by finding its parent node to the initial node)
depth = 0
nodePrt = open[0][4]
if nodePrt == 0:
depth = 0
else:
while True:
for i in range(len(closed)):
if nodePrt == closed[i][3]:
depth = depth + 1
nodePrt = closed[i][4]
if nodePrt == 0:
break

#Extend left
if side == 'left' or side == '':
if y > 0:
if_final = 0
crtLeft = exchange(src, x, y, x, y - 1)
leftCost = manhattan(numberFinal, crtLeft) + depth
nodeid = nodeid + 1
if manhattan(numberFinal, crtLeft) == 0:
if_final = 1
rtResult.append([crtLeft, src, leftCost, nodeid, if_final])
#Extend right
if side == 'right' or side == '':
if y < 2:
if_final = 0
crtRight = exchange(src, x, y, x, y + 1)
rightCost = manhattan(numberFinal, crtRight) + depth
nodeid = nodeid + 1
if manhattan(numberFinal, crtRight) == 0:
if_final = 1
rtResult.append([crtRight, src, rightCost, nodeid, if_final])
#Expand up
if side == 'up' or side == '':
if x > 0:
if_final = 0
crtUp = exchange(src, x, y, x - 1, y)
upCost = manhattan(numberFinal, crtUp) + depth
nodeid = nodeid + 1
if manhattan(numberFinal, crtUp) == 0:
if_final = 1
rtResult.append([crtUp, src, upCost, nodeid,if_final])
#Extend down
if side == 'down' or side == '':
if x < 2:
if_final = 0
crtDown = exchange(src, x, y, x + 1, y)
depth = depth + 1
downCost = manhattan(numberFinal, crtDown) + depth
nodeid = nodeid + 1
if manhattan(numberFinal, crtDown) == 0:
if_final = 1
rtResult.append([crtDown, src, downCost, nodeid, if_final])
return rtResult

## 5.3. Open table handler

def handleOpen():
Global nodeid # records the number of extension nodes
global open
while True:
if len(open) == 0:
break
x = 0
tmpOpen = open[0]

tmp = expand(open[0][0], '')
for y in range(len(tmp)):
flag = False
for j in range(len(open)):
if tmp[y][0] == open[j][0]:
flag = True
for k in range(len(closed)):
if tmp[y][0] == closed[k][0]:
flag = True
if not flag:

If TMP [y] [4] = = 1: # judge whether to reach the final node
closed.append(tmpOpen)
closed.append(open[0])
open.remove(open[0])
print('Totally', nodeid, 'nodes ayalyzed,find the result.')
prtResult()
print('Success!')
exit("We find it!")
closed.append(tmpOpen)
open.remove(tmpOpen)

## 5.4. Backtracking by node code

#Start from the last item of the close table, find the previous node until the previous node is 0, write all the found sequences to step and print out step
def prtResult():
step = [closed[-1]]
nodePrt = closed[-1][4]
while True:
for x in range(len(closed)):
if nodePrt == closed[x][3]:
step.insert(0, closed[x])
nodePrt = closed[x][4]
if nodePrt == 0:
break
for x in range(len(step)):
print('Step', x, ':')
prtNum(step[x][0])
print('Finished!')
time.sleep(10)

## 5.5. Main function

if __name__ == '__main__':
#Initialization
open = []
closed = []
nodeid = 1

#Enter the initial and target sequences and print them out for confirmation
while True:
tmp = input()
numberOrig = [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8]]
tmp = input()
numberFinal = [tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5], tmp[6], tmp[7], tmp[8]]
print('Orig is')
prtNum(numberOrig)
print('Final is')
prtNum(numberFinal)
if (judge(numberOrig) + judge(numberFinal)) % 2 == 0:
print('Have answer! Orig is ', judge(numberOrig), ', Final is', judge(numberFinal))
#Extract the digital location of the target node

#Add the initial node to the open table and start processing.
open.append([numberOrig, 'NULL', manhattan(numberOrig, numberFinal), 1, 0, 0])
handleOpen()
else:
print('No answer! Orig is ', judge(numberOrig), ', Final is', judge(numberFinal))

## 6. Test results

Orig is
0 1 2
3 4 5
6 7 8
Final is
1 2 3
4 5 0
6 7 8
Have answer! Orig is  0 , Final is 0
Totally 474 nodes ayalyzed,find the result.
Step 0 :
0 1 2
3 4 5
6 7 8
Step 1 :
1 0 2
3 4 5
6 7 8
Step 2 :
1 2 0
3 4 5
6 7 8
Step 3 :
1 2 5
3 4 0
6 7 8
Step 4 :
1 2 5
3 0 4
6 7 8
Step 5 :
1 2 5
0 3 4
6 7 8
Step 6 :
0 2 5
1 3 4
6 7 8
Step 7 :
2 0 5
1 3 4
6 7 8
Step 8 :
2 5 0
1 3 4
6 7 8
Step 9 :
2 3 5
1 0 4
6 7 8
Step 10 :
2 3 5
1 4 0
6 7 8
Step 11 :
2 3 0
1 4 5
6 7 8
Step 12 :
2 0 3
1 4 5
6 7 8
Step 13 :
0 2 3
1 4 5
6 7 8
Step 14 :
1 2 3
0 4 5
6 7 8
Step 15 :
1 2 3
4 0 5
6 7 8
Step 16 :
1 2 3
4 5 0
6 7 8
Finished!
Success!
We find it!

## Win11 dev preview 22509.1011 update patch kb5008918 release (with more detailed summary)

Microsoft officially released the latest Windows 11 dev preview 22509 system update. This new version provides new layout options for the “start” menu, improves the edge + narrator experience, and fixes a series of bug bugs. Microsoft has released another “service pipeline” update, which is a cumulative update for windows 11 dev preview 22509. Version […]