Python 优化8字谜
我是一名初级程序员,我试图用广度优先搜索来解决8字谜问题,但解决这个问题花了太长时间,我想优化我的代码。 配置:Python 优化8字谜,python,python-3.x,optimization,Python,Python 3.x,Optimization,我是一名初级程序员,我试图用广度优先搜索来解决8字谜问题,但解决这个问题花了太长时间,我想优化我的代码。 配置:[[5,4,3],[0,7,2],[6,1,8]将在22.623718615秒内解决, 配置[[8,0,6],[5,4,7],[2,3,1]占用了235.721346421秒。 我想减少求解时间。 这是我的代码: from copy import deepcopy from collections import deque from time import perf_counter
[[5,4,3],[0,7,2],[6,1,8]
将在22.623718615
秒内解决,
配置[[8,0,6],[5,4,7],[2,3,1]
占用了235.721346421
秒。
我想减少求解时间。
这是我的代码:
from copy import deepcopy
from collections import deque
from time import perf_counter
most_hard = [[8, 0, 6], [5, 4, 7], [2, 3, 1]] # 30 moves
class CheckPuzzle:
def __init__(self, puzzle: list):
self.puzzle = puzzle
self.len = len(puzzle)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
if not self.is_valid():
raise TypeError("Puzzle is not valid")
elif not self.is_solvable():
raise Exception("Unsolvable puzzle")
# создай ф-ию check
def sum_of_numbers(self) -> int:
return sum(self.convert_to_1d(self.goal))
def sum_of_squares(self) -> int:
return sum([i ** 2 for i in self.convert_to_1d(self.goal)])
def is_valid(self) -> bool:
sum_of_numbers = 0
sum_of_squares = 0
for row in range(self.len):
for column in range(self.len):
sum_of_numbers += self.puzzle[row][column]
sum_of_squares += (self.puzzle[row][column]) ** 2
return sum_of_numbers == self.sum_of_numbers() and sum_of_squares == self.sum_of_squares()
def convert_to_1d(self, board) -> list:
one_dimension_matrix = []
for row in range(self.len):
for column in range(self.len):
one_dimension_matrix.append(board[row][column])
return one_dimension_matrix
def inversion(self, board) -> int:
inversion = 0
one_dimension_matrix = self.convert_to_1d(board)
for index in range(len(one_dimension_matrix)):
temp = one_dimension_matrix[index]
if temp == 0 or temp == 1:
continue
for elem in one_dimension_matrix[index:]:
if elem == 0:
continue
if temp > elem:
inversion += 1
return inversion
def is_solvable(self) -> bool:
inv_of_matrix = self.inversion(self.puzzle)
inv_of_goal_matrix = self.inversion(self.goal)
return (inv_of_matrix % 2 == 0 and inv_of_goal_matrix % 2 == 0) or \
(inv_of_matrix % 2 == 1 and inv_of_goal_matrix % 2 == 1)
class Puzzle:
def __init__(self, board: list):
self.board = board
self.len = len(board)
if self.len == 3:
self.goal = [[1, 2, 3],
[4, 5, 6],
[7, 8, 0]]
elif self.len == 4:
self.goal = [[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
def print_matrix(self) -> str:
output = ''
for row in self.board:
for elem in row:
output += str(elem) + " "
output += '\n'
return output
def get_index(self, matrix, value) -> tuple:
for i in range(self.len):
for j in range(self.len):
if matrix[i][j] == value:
return i, j
def manhattan(self):
distance = 0
for i in range(self.len):
for j in range(self.len):
if self.board[i][j] != 0:
x, y = divmod(self.board[i][j] - 1, self.len)
distance += abs(x - i) + abs(y - j)
return distance
def list_of_possible_moves(self) -> list:
x, y = self.get_index(self.board, 0)
possible_moves = []
if x > 0:
possible_moves.append((x - 1, y))
if x < self.len - 1:
possible_moves.append((x + 1, y))
if y > 0:
possible_moves.append((x, y - 1))
if y < self.len - 1:
possible_moves.append((x, y + 1))
return possible_moves
def move(self, to: tuple) -> list:
moving_board = deepcopy(self.board)
x, y = self.get_index(self.board, 0)
i, j = to
moving_board[x][y], moving_board[i][j] = moving_board[i][j], moving_board[x][y]
return moving_board
def solved(self) -> bool:
return self.board == self.goal
def __str__(self) -> str:
return ''.join(map(str, self))
def __iter__(self):
for row in self.board:
yield from row
class Node:
def __init__(self, puzzle, parent=None):
self.puzzle = puzzle
self.parent = parent
if self.parent:
self.g = parent.g + 1
else:
self.g = 0
def state(self) -> str:
return str(self)
def path(self):
node, p = self, []
while node:
p.append(node)
node = node.parent
yield from reversed(p)
def solved(self) -> bool:
return self.puzzle.solved()
def pretty_print(self) -> str:
return self.puzzle.print_matrix()
def h(self) -> int:
return self.puzzle.manhattan()
def f(self) -> int:
return self.h() + self.g
def all_moves(self) -> list:
return self.puzzle.list_of_possible_moves()
def __str__(self) -> str:
return str(self.puzzle)
def make_a_move(self, to: tuple) -> list:
return self.puzzle.move(to)
class GameTree:
def __init__(self, root):
self.root = root
def solve(self):
queue = deque([Node(self.root)])
seen = set()
seen.add(queue[0].state())
while queue:
queue = deque(sorted(list(queue), key=lambda node: node.f()))
node = queue.popleft()
if node.solved():
return node.path()
for move in node.all_moves():
moved = node.make_a_move(move)
child = Node(Puzzle(moved), node)
if child.state() not in seen:
queue.append(child)
seen.add(child.state())
def main():
a = [[5, 4, 3], [0, 7, 2], [6, 1, 8]]
c = Puzzle(a)
d = GameTree(c)
tic = perf_counter()
p = d.solve()
toc = perf_counter()
step = 0
for i in p:
print(i.pretty_print())
step += 1
print(step)
print(toc-tic)
if __name__ == "__main__":
main()
从复制导入deepcopy
从集合导入deque
从时间导入性能计数器
大部分难度=[8,0,6],[5,4,7],[2,3,1]#30步
类支票拼图:
定义初始化(自我,谜题:列表):
self.puzzle=puzzle
self.len=len(拼图)
如果self.len==3:
self.goal=[[1,2,3],
[4, 5, 6],
[7, 8, 0]]
elif self.len==4:
self.goal=[[1,2,3,4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
如果不是self.u有效():
raise TypeError(“拼图无效”)
elif not self.is_solvable():
引发异常(“无法解决的难题”)
#检查
定义数字之和(自)->int:
返回和(自我转换为自我目标)
定义平方和(自)->int:
返回和([i**2表示自我中的i.convert\u为自我1d(self.goal)])
def有效(自)->bool:
_个数之和=0
平方和=0
对于范围内的行(self.len):
对于范围内的列(self.len):
数字之和+=自我拼图[行][列]
平方和+=(自拼图[行][列]**2
返回self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self.self
def convert_to_1d(自身、电路板)->列表:
一维矩阵=[]
对于范围内的行(self.len):
对于范围内的列(self.len):
一维矩阵。追加(板[行][列])
返回一维矩阵
def反转(自、板)->int:
反转=0
一维矩阵=自。将一维转换为一维(板)
对于范围内的索引(len(一维矩阵)):
temp=一维矩阵[索引]
如果温度=0或温度=1:
持续
对于一维矩阵中的元素[索引:]:
如果elem==0:
持续
如果温度>元素:
反转+=1
返回反转
def可解(自)->bool:
_矩阵的inv_=self.inversion(self.puzzle)
目标矩阵的inv\u=self.inversion(self.goal)
返回(矩阵%2的库存=0,目标矩阵%2的库存=0)或\
(矩阵%2的库存=1,目标矩阵%2的库存=1)
班级难题:
定义初始化(自我,电路板:列表):
self.board=board
self.len=len(板)
如果self.len==3:
self.goal=[[1,2,3],
[4, 5, 6],
[7, 8, 0]]
elif self.len==4:
self.goal=[[1,2,3,4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 0]]
def打印矩阵(自身)->str:
输出=“”
对于self.board中的行:
对于行中的元素:
输出+=str(元素)+“
输出+='\n'
返回输出
def get_索引(自身、矩阵、值)->元组:
对于范围内的i(self.len):
对于范围内的j(自透镜):
如果矩阵[i][j]==值:
返回i,j
def曼哈顿(自我):
距离=0
对于范围内的i(self.len):
对于范围内的j(自透镜):
if self.board[i][j]!=0:
x、 y=divmod(自板[i][j]-1,自透镜)
距离+=abs(x-i)+abs(y-j)
返回距离
def list_of_可能的_移动(自)->列表:
x、 y=self.get_索引(self.board,0)
可能的_移动=[]
如果x>0:
可能的_移动。追加((x-1,y))
如果x0:
可能的_移动。追加((x,y-1))
如果y列表:
移动电路板=深度复制(self.board)
x、 y=self.get_索引(self.board,0)
i、 j=至
移动电路板[x][y],移动电路板[i][j]=移动电路板[i][j],移动电路板[x][y]
回程板
def已解决(自)->bool:
返回self.board==self.goal
定义(自我)->str:
返回“”。加入(映射(str,self))
定义(自我):
对于self.board中的行:
行产量
类节点:
def uuu init uuu(self,puzzle,parent=None):
self.puzzle=puzzle
self.parent=parent
如果self.parent:
self.g=parent.g+1
其他:
self.g=0
def状态(自身)->str:
返回str(self)
def路径(自身):
节点,p=self,[]
while节点:
p、 附加(节点)
node=node.parent
反向收益率(p)
def已解决(自)->bool:
return self.puzzle.solved()
def pretty_打印(自)->str:
return self.puzzle.print_matrix()
def h(自)->int:
return self.puzzle.manhattan()
def f(自)->int:
返回self.h()+self.g
定义所有移动(自)->列表:
return self.puzzle.list\u可能的移动()
定义(自我)->str:
返回str(self.puzzle)
def make_a_move(self,to:tuple)->列表:
返回自我。拼图。移动(到)
类游戏树:
定义初始化(自,根):
self.root=根
def解算(自):
queue=deque([Node(self.root)])
seen=set()
西元