优化速度 Python 的循环



就像指出的那样,让我解释一些代码。我有 2 个 for 循环,因为我有一个名为 Tablut 的游戏板。我必须从棋子位置(row_index和column_index(检查左侧和右侧是否有障碍物。因此,第一个循环取row_index棋子,然后检查右侧的每一行,并在发现障碍物时停止。然后对左侧执行相同的操作。如果我使用单个循环,如果发现障碍物并开始向另一个方向查找,我没有办法停止向一个方向搜索,因为中断将停止整个 for。循环用于生成移动在该回合中可以在棋盘内执行的所有可能操作。Action(Position(....((是棋子可以做出的一个动作。

所以,基本上,我检查左右方向,如果下一个图块为空,我可以移动到那里,所以我创建一个新动作并将其添加到所有可能移动的列表中,如果有障碍物,因为我不能跳它,我停止循环。

我有这个循环,我想优化它的速度。

for row in range(row_index - 1, -1, -1):
if bitboard_util.get_bit(obstacle_bitboard, row, column_index) != 1:
action = Action(Position(row_index, column_index), Position(row, column_index), color)
all_available_moves_for_pawn.append(action)
else:
break
for row in range(row_index + 1, 9):
if bitboard_util.get_bit(obstacle_bitboard, row, column_index) != 1:
action = Action(Position(row_index, column_index), Position(row, column_index), color)
all_available_moves_for_pawn.append(action)
else:
break

您可以通过根据您的障碍物位准备一个结构来稍微优化这一点,该结构将为每个位置提供可用的"移动"范围。 您可以准备一次该结构,然后多次重复使用,以便以后直接获取所有column_index/row_index的移动列表。

from itertools import accumulate
rowCount = 9
colCount = 9
obstacleRanges = []
for col in range(colCount):
obstacles     = [-1] + [ row*(bitboard_util.get_bit(obstacle_bitboard, row, col) == 1) for row in range(rowCount) ] + [rowCount]
prevObstacle  = [*accumulate(obstacles,max)]
nextObstacle  = [*accumulate(obstacles[::-1],lambda p,o:[p,o][o>0])][::-1]
obstacleRanges.append([*zip(prevObstacle[1:-1],nextObstacle[1:-1])])

obstacleRanges将包含元组,其中包含板上每个位置的上一个和下一个障碍物的位置(行(。 这是为整个板计算一次,允许您直接找到移动范围,而无需额外调用get_bit

用法:

prevObstacle,nextObstacle = obstacleRanges[column_index,row_index]
for moveRow in range(prevObstacle+1, nextObstacle):
action = Action(Position(row_index, column_index), Position(moveRow, column_index), color)
all_available_moves_for_pawn.append(action)

请注意,这可能会也可能不会提高性能,具体取决于棋子的分布和数量,以及您查询具有相同障碍物布局的操作的次数。 例如,如果您的棋子是障碍物并且它们正在移动,则最好使用棋子移动的效果更新结构,而不是完全重新计算它。

最新更新