# Here comes the reference answer to the python exercise question (super code). Have a look?

A few basic python grammar topics have been posted earlier, which are mainly used to help test the mastery of basic knowledge. If you have carefully read or done them, I believe you should have a certain understanding of your mastery of knowledge. Next, you can relearn the part that is not very clear.

python basic syntax is OK? Do some tests

python basic syntax is OK? Do some tests (2)

python solution is OK? Do some tests (3)

Among the above three articles, the first and second articles are relatively simple. The content of the third article is indeed difficult if you have not specially studied the content related to data structure and algorithm. This is the opposite. Let's put the reference answers of the most difficult article first, and put the first and second articles in the next issue.

If you haven't read the third article, I suggest you think about it yourself first and try it according to your existing knowledge. Efficient learning or learning effect learning must produce a lot of effective thinking per unit time - that is, you have tried hard and tried various methods, but these thoughts are very helpful. You know your puzzles and problems to be solved; When you see the reference answer, it is completely different from those who have not thought. When these contents are successfully solved, your brain should make subtle changes in the game and make breakthroughs in technology.

Now officially enter the topic.

In order to make you better understand the following contents, let's talk about some larger concepts first.

Cycle of violence (exhaustive): most computer problems can be solved by exhaustive without considering time.

For example, we can find out all the schemes through exhaustive methods, and then find the one with the least quantity.

The same is true for Sudoku. There are four possibilities for each position. You can list all methods, and then judge the coincidence.

Similarly, the maze problem is the same.

The cycle of violence mentioned above is simple, but there are also some problems to face:

1. How to ensure that all the information can be listed without omission?
1. For example, how many non repeated 3 digits can be combined from 3, 4, 5, 6 and 4 numbers?
2. 24 point game, random four numbers, 1, 3, 6, 9, plus, minus, multiplication and division (+ - * /), parentheses, how many situations can be combined?
2. How to judge whether the current situation is inconsistent? Different problems lead to different difficulties. It's easy to judge the change. Maze and Sudoku are a little more troublesome.
3. There is a large amount of data. It has been a long time without results. How can we speed up some speed?
4. ......

To solve some of the above problems, we need to have some strategies, such as how to ensure that the poor cite all the cases, and the permutation and combination in mathematics is very popular.

There are many ways to realize permutation and combination. For example, I have used multiple loops before, and of course I can also use recursion.

Full Permutation and combination implementation method

This method ensures that there is no leakage. The tree structure and many decision trees are similar.

Question 2 specific analysis.

Problem 3: to reduce the data scale is to use recursion to calculate Fibonacci series. After 40 items are calculated, it is not increased once. The time is double. The computer card is stuck for a long time. The reason is repeated calculation. You can save the calculated values through a list and reduce repeated calculation, which will significantly improve the speed.

For example, if you find the target number in a range and judge it one by one from beginning to end, it must be slow. Two point search can cut half at a time. How large the range is, it becomes smaller after several times.

1. Find the smallest tuple value in the following list, and the maximum value is the same.

`[(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11), (12, 13, 14), (15, 16, 17), (18, 19, 20), (21, 22, 23), (24, 25, 26)]`

result:

```Minimum:(0, 1, 2)
Maximum:(24, 25, 26)```

2. Find the most frequent element in the following list and print the number.

`l = [1,3,4,5,6,1,3,4,5,1,9,1,1,1]`

result:

`1 Up to 6 times.`

Reference for questions 1 and 2: python mosaic pixel map , which gives the solution.

3. Change problem

Given the types of change that can be found and the total amount of change to be found, find the scheme of the least amount of change.

For example, change 6 yuan,

Scheme 1: 4 1;

Scheme 2: 3,3;

Scheme 3: 3,1,1,1;

Scheme 4: 1,1,1,1,1,1;

Obviously, scheme 2 has the least number, only 2.

```values = [1, 3, 4]  # Coin face value
total = 6  # I need change```

result:

`[3,3]`

Refer to answer 1 - local optimal solution:

```# Target number of change
total = 6
# Types of banknotes
values = [4, 3, 1]
# result
number = [0,0,0]

# Cycle, starting from the maximum face value
for i in range(3):
# Rounding to calculate the maximum number of sheets that can be found for the current face value
number[i] = total // values[i]
# Take the balance and calculate the amount of money left after the change of the current face value
total = total % values[i]

for i in range(3):
print(values[i],'The number of sheets of yuan is:',number[i],'Zhang')```

Reference answer 2 - global optimal solution (dynamic programming):

I'm too lazy to write. I found a number on the Internet and changed it. I feel it's still very clear

```def rec_mc(coin_value_list, change, know_results):
min_coins = change
if change in coin_value_list:
know_results[change] = 1
return 1
elif know_results[change] > 0:
return know_results[change]
else:
for i in [c for c in coin_value_list if c <= change]:
num_coins = 1 + rec_mc(coin_value_list, change-i, know_results)
if num_coins < min_coins:
min_coins = num_coins
know_results[change] = min_coins
return min_coins

print("===========Recursive implementation========================")
print(rec_mc([1, 3, 4], 6, [0]*7))

def dp_make_change(coin_value_list, change, min_coins, coins_used):
for cents in range(change+1):
coin_count = cents
new_coin = 1
for j in [c for c in coin_value_list if c <= cents]:
if min_coins[cents-j] + 1 < coin_count:
coin_count = min_coins[cents-j]+1
new_coin = j
min_coins[cents] = coin_count
coins_used[cents] = new_coin
return min_coins[change]

def print_coins(coins_used, change):
coin = change
while coin > 0:
this_coin = coins_used[coin]
print(this_coin)
coin = coin - this_coin

a_mnt = 6
c_list = [1, 3, 4]
c_used = [0] * (a_mnt+1)
c_count = [0] * (a_mnt+1)
print("===========Dynamic programming implementation========================")
print('Making change for ', a_mnt, 'requires')
print(dp_make_change(c_list, a_mnt, c_count, c_used), 'coins')
print("They are: ")
print_coins(c_used, a_mnt)
print("The used list is as follows: ")
print(c_used)```

4. Sudoku 4

Using the program to automatically complete 4 * 4 Sudoku

```[[0, 1, 0, 0],
[0, 0, 0, 2],
[3, 0, 0, 0],
[0, 0, 4, 0]]```

result:

```# Print board
def print_board(board):
for row in board:
print(row)

def check_board(num,row,col):
# Check the row and judge each grid of the row
for i in range(cols):
# If the number to be filled already exists
if board[row][i] == num:
return False
# Check the column and judge each grid of the column
for i in range(rows):
# If the number to be filled already exists
if board[i][col] == num:
return False
return True

def backtrack(board, index):
if index >= 16:
print("----programme----")
print_board(board)
print("------------")
else:
for num in range(1, len(board)+1):
row = index//len(board)
col = index%len(board[0])
if board[row][col]==0:
# Judge whether this number can be filled in
if not check_board(num, row, col):
continue
# Select a number
board[row][col] = num
backtrack(board,index+1)
# Number of unselected
board[row][col] = 0
else:
index = index +1
rows = 4
cols = 4
board = [[0 for i in range(rows)] for j in range(cols)]
board[0][1] = 1
board[1][3] = 2
board[2][0] = 3
board[3][2] = 4
index = 0
backtrack(board,index)```

Unpackaged visual Sudoku version:

```from PIL import Image, ImageDraw
import matplotlib.pyplot as plt
#Title Setting Chinese
plt.rc("font", family='MicroSoft YaHei', weight='bold')
plt.ion()

# Print board
def print_board(board):
for row in board:
print(row)

def show_board(board, x, y, num):
img = Image.new("RGB", (100, 100), "white")
draw = ImageDraw.Draw(img)
for row in range(4):
for col in range(4):
pos = (0+30*col, 0+row*30)
draw.text(pos, str(board[row][col]), fill=(0, 0, 255))
draw.text((0+30*y, 0+x*30), str(num), fill=(255, 0, 255))
return img

def check_board(num, row, col):
# Check the row and judge each grid of the row
for i in range(cols):
# If the number to be filled already exists
if board[row][i] == num:
return False
# Check the column and judge each grid of the column
for i in range(rows):
# If the number to be filled already exists
if board[i][col] == num:
return False
return True

def backtrack(board, index):
if index >= 16:
print("----programme----")
print_board(board)
print("------------")
img = show_board(board, 3, 3, board[3][3])
plt.title("Compliant scheme")   # title
plt.imshow(img)
plt.pause(5)  # Pause for 1 second
else:
for num in range(1, 4+1):
row = index//4
col = index % 4
if board[row][col] == 0:
# Judge whether this number can be filled in
if not check_board(num, row, col):
continue
# Select a number
board[row][col] = num
plt.cla()  # Clear the screen first
img = show_board(board, row, col, num)
plt.title("Fill in a number")   # title
plt.imshow(img)
plt.pause(1)  # Pause for 1 second
backtrack(board, index+1)
# Number of unselected
board[row][col] = 0
plt.cla()  # Clear the screen first
img = show_board(board, row, col, num)
plt.title("Cancel a number")   # title
plt.imshow(img)
plt.pause(1)  # Pause for 1 second
else:
index = index + 1

rows = 4
cols = 4
board = [[0 for i in range(rows)] for j in range(cols)]
board[0][1] = 1
board[1][3] = 2
board[2][0] = 3
board[3][2] = 4
# plt.pause(5)
img = show_board(board, 3, 3, board[3][3])
plt.title("4X4 Sudoku game")   # title
plt.imshow(img)
plt.pause(5)
plt.title("start")
plt.pause(2)
index = 0
backtrack(board, index)
plt.pause(2)  # Pause for 1 second
plt.ioff()
plt.show()```

5. Sudoku 9

Increase the difficulty and use the program to automatically complete 9 * 9 Sudoku.

```[[2, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 6, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 9, 0, 2, 0, 0],
[0, 5, 0, 0, 0, 7, 0, 0, 0],
[0, 0, 0, 0, 4, 5, 7, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 3, 0],
[0, 0, 1, 0, 0, 0, 0, 6, 8],
[0, 0, 8, 5, 0, 0, 0, 1, 0],
[0, 9, 0, 0, 0, 0, 4, 0, 0]]```

Results: there are many answers, and only some are listed below.

```# Print board
def print_board(board):
for row in board:
print(row)

def check_board(num,row,col):
# Check whether there are duplicate numbers in the row and column
for i in range(9):
if board[row][i] == num or board[i][col] == num:
return False

# Judge whether there is repetition in xiaojiugong
sub_row = row // 3
sub_col = col // 3
for i in range(3):
for j in range(3):
if board[sub_row * 3 + i][sub_col * 3 + j] == num:
return False
return True

def backtrack(board, index):
# print(index)
if index >= 81:
print("-----------programme-----------")
print_board(board)
print("--------------------------")
else:
for num in range(1, 9+1):
row = index//9
col = index%9
if board[row][col]==0:
# Judge whether this number can be filled in
if not check_board(num, row, col):
continue
# Select a number
board[row][col] = num
# Continue to select the next number
backtrack(board,index+1)
# Number of unselected
board[row][col] = 0
else:
# backtrack(board,index+1)
index = index + 1

board = [[2, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 6, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 9, 0, 2, 0, 0],
[0, 5, 0, 0, 0, 7, 0, 0, 0],
[0, 0, 0, 0, 4, 5, 7, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 3, 0],
[0, 0, 1, 0, 0, 0, 0, 6, 8],
[0, 0, 8, 5, 0, 0, 0, 1, 0],
[0, 9, 0, 0, 0, 0, 4, 0, 0]]

index = 0
backtrack(board,index)```

Unpackaged visual Sudoku version:

```from PIL import Image,ImageDraw
import matplotlib.pyplot as plt
#Title Setting Chinese
plt.rc("font", family='MicroSoft YaHei', weight='bold')
plt.ion()

# Print board
def print_board(board):
for row in board:
print(row)

def show_board(board,x,y,num):
img = Image.new("RGB", (250, 250), "white")
draw = ImageDraw.Draw(img)
for row in range(9):
for col in range(9):
pos = (0+30*col, 0+row*30)
draw.text(pos, str(board[row][col]), fill=(0, 0, 255))
draw.text((0+30*y, 0+x*30), str(num), fill=(255, 0, 255))
return img

def check_board(num, row, col):
# Check whether there are duplicate numbers in the row and column
for i in range(9):
if board[row][i] == num or board[i][col] == num:
return False

# Judge whether there is repetition in xiaojiugong
sub_row = row // 3
sub_col = col // 3
for i in range(3):
for j in range(3):
if board[sub_row * 3 + i][sub_col * 3 + j] == num:
return False
return True

def backtrack(board, index):
global count
# print(index)
if index >= 81:
count = count + 1
img = show_board(board, 8, 8, board[8][8])
plt.title("The first{}Suspension of 1 eligible scheme s".format(count))   # title
plt.imshow(img)
plt.pause(1)  # Pause for 1 second
plt.title("Next plan")   # title
plt.pause(1)  # Pause for 1 second
print("-----------------------")
print_board(board)
else:
for num in range(1, 9+1):
row = index//9
col = index % 9
if board[row][col] == 0:
# Judge whether this number can be filled in
if not check_board(num, row, col):
continue
# Select a number
board[row][col] = num
plt.cla()  # Clear the screen first
img = show_board(board,row,col,num)
plt.title("Fill in a number")   # title
plt.imshow(img)
plt.pause(0.1)  # Pause for 1 second
# Continue to select the next number
backtrack(board, index+1)
# Number of unselected
board[row][col] = 0
plt.cla()  # Clear the screen first
img = show_board(board,row,col,num)
plt.title("Cancel a number")   # title
plt.imshow(img)
plt.pause(0.1)  # Pause for 1 second
else:
# backtrack(board,index+1)
index = index + 1
plt.cla()  # Clear the screen first
board = [[2, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 6, 0, 0, 0, 0, 0],
[0, 7, 0, 0, 9, 0, 2, 0, 0],
[0, 5, 0, 0, 0, 7, 0, 0, 0],
[0, 0, 0, 0, 4, 5, 7, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 3, 0],
[0, 0, 1, 0, 0, 0, 0, 6, 8],
[0, 0, 8, 5, 0, 0, 0, 1, 0],
[0, 9, 0, 0, 0, 0, 4, 0, 0]]

img = show_board(board, 8, 8, board[8][8])
plt.title("9X9 Sudoku game")   # title
plt.imshow(img)
plt.pause(2)
plt.title("start")
plt.pause(2)
index = 0
global count
count = 0
backtrack(board, index)
# plt.ioff()
plt.show()```

6. Maze problem

A maze with a size of 5 * 6 is given, which is composed of channel (0) and wall (1), in which the upper left corner of the channel represents the starting point and the lower right corner of the channel represents the end point. Find the maze path.

```maze = [[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 1, 0],
[1, 1, 1, 0, 0],
[0, 1, 0, 0, 1],
[0, 1, 0, 0, 0]]```

result:

```[[0, 0], [1, 0], [1, 1], [1, 2], [0, 2], [0, 3], [0, 4],
[1, 4], [2, 4], [3, 4], [3, 3], [4, 3], [5, 3], [5, 4]]```

```# Shortest distance shortest path
maze =[[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 1, 0]]
n,m = len(maze),len(maze[0])
start = [0, 0]
end = [4, 4]
# List of data to be found
search_queue = []  # List simulation queue
# Add start point
search_queue.append(start)
visted = []  # Record visited points
visted.append(start)

def find_next_point(point):
global search_queue,visted,n,m
# px and py arrays are used to realize the moving order of bottom left and top right
px = [-1, 0, 1, 0]
py = [0, -1, 0, 1]
# Move up, down, left and right
for i in range(4):
next_x = point[0] + px[i]
next_y = point[1] + py[i]
# How to add the next point to the queue to be searched and the access queue to meet the requirements
if (0 <= next_x < n and 0 <= next_y < m and maze[next_x][next_y] == 0 and [next_x,next_y] not in visted):
search_queue.append([next_x,next_y])
visted.append([next_x,next_y])
return True
return False

def dfs():
global search_queue,visted
print(search_queue)
while search_queue[-1] != end:
# Get the last point of the queue and judge whether to reach the big end point
point = search_queue[-1]
# If there is a next point, continue
if find_next_point(point):
continue
# Otherwise, delete the point you just added
else:
print("delete",search_queue.pop())
print(search_queue)

dfs()```

The above is difficult to understand. You can see the following. I found a simple change on the Internet. It is easier to understand, but there are many codes

```def up(point):
# You have reached the top of the array. You can't go up
if point[0] == 0:
return False
else:
new_point = [point[0] - 1, point[1]]
# The road we have traveled is no longer gone
if new_point in visted:
return False
# Don't go against the wall
elif maze[new_point[0]][new_point[1]] == 1:
return False
else:
search_queue.append(new_point)
visted.append(new_point)
return True

def down(point):
# When you meet the bottom of the maze, you can't go further
if point[0] == len(maze) - 1:  # The number of two-dimensional array rows with 6 rows and 5 columns is calculated from 0, so it is 6-1 = 5 rows
return False
else:
new_point = [point[0] + 1, point[1]]
# The road we have traveled is no longer gone
if new_point in visted:
return False
# Don't go against the wall
elif maze[new_point[0]][new_point[1]] == 1:
return False
else:
visted.append(new_point)
search_queue.append(new_point)
return True

def left(point):
# You can't continue to go left when you meet the leftmost part of the maze
if point[1] == 0:
return False
else:
new_point = [point[0], point[1] - 1]
# The road we have traveled is no longer gone
if new_point in visted:
return False
# Don't go against the wall
elif maze[new_point[0]][new_point[1]] == 1:
return False
else:
visted.append(new_point)
search_queue.append(new_point)
return True

def right(point):
# You cannot continue to move to the right when you encounter the rightmost side of the maze
if point[1] == len(maze[0]) - 1:  # The number of two-dimensional array columns with 6 rows and 5 columns is calculated from 0, so it is 5-1 = 4 rows
return False
else:
new_point = [point[0], point[1] + 1]
# The road we have traveled is no longer gone
if new_point in visted:
return False
# Don't go against the wall
elif maze[new_point[0]][new_point[1]] == 1:
return False
else:
visted.append(new_point)
search_queue.append(new_point)
return True

maze = [[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 1, 0],
[1, 1, 1, 0, 0],
[0, 1, 0, 0, 1],
[0, 1, 0, 0, 0]]
start = [0, 0]
end = [5, 4]

search_queue = []
visted = []
search_queue.append(start)
visted.append(start)

print("start: %s --> end: %s\n" % (start, end))
while search_queue[-1] != end:
now = search_queue[-1]
if up(now) or down(now) or left(now) or right(now):
continue
print("delete",search_queue.pop())

print("final path: ", search_queue)```

7. Maze problem 2 - shortest path.

Given a maze with a size of 5 * 5, it is composed of channel (0) and wall (1), in which the upper left corner of the channel represents the starting point and the lower right corner of the channel represents the end point, so as to find the shortest path of the maze.

```maze = [[0, 1, 0, 0, 0,],
[0, 1, 0, 1, 0,],
[0, 0, 0, 0, 0,],
[0, 1, 1, 1, 0,],
[0, 0, 0, 1, 0,]]```

There are two schemes, but scheme 2 is the shortest path.

```# Shortest distance shortest path
maze =[[0, 1, 0, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 0, 1, 0]]
n,m = len(maze),len(maze[0])
start = [0, 0]
end = [4, 4]

# Define the Breadth First Search algorithm
def bfs(maze,n,m):
# List of data to be found
search_queue = []  # List simulation queue
# Add start point
search_queue.append(start)
visted = []  # Record visited points
visted.append(start)
# Record parent node
parent = {f"{start[0]}{start[1]}":None}
px = [-1, 0, 1, 0]   # px and py arrays are used to realize the moving order of bottom left and top right
py = [0, -1, 0, 1]
# Exit the loop until the lookup queue is empty
while search_queue:
# Take out the first point in the queue (search started recently)
point = search_queue.pop(0)
# Get all nearest points
points = []
for i in range(4):
next_x = point[0] + px[i]
next_y = point[1] + py[i]
if (0 <= next_x < n and 0 <= next_y < m and maze[next_x][next_y] == 0):
points.append([next_x,next_y])
for i in points:
# If i have not been visited
if i not in visted:
# Add I (nearest point) to the search queue
search_queue.append(i)
# Mark i as accessed
visted.append(i)
# Record the parent node of each point
parent[f"{i[0]}{i[1]}"] = point
return visted,parent

visted,parent = bfs(maze,n,m)

route_list = []
if end in visted:
print(f"Existence from{start}reach{ end}Route")
v = end # Currently accessed point
# Until the start position None exits
while v !=None:
route_list.append(v)
v=parent[f"{v[0]}{v[1]}"]
else:
print(f"Does not exist from{start}reach{ end}Route")
route_list.reverse()
print(route_list)```

How to see the above methods is difficult. You can look at the concepts of DFS and BFS, backtracking, recursion and so on. You can also take a look at what I wrote before. I have time to update it later. What I wrote before is not very good. I can make do with it.

Recursive algorithm (I)

Recursive algorithm (Part 2)

Full Permutation and combination implementation method

Thoughts on learning algorithms (end of full text)

Added by dbair on Thu, 30 Dec 2021 22:03:16 +0200