Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 15个谜题的这个实现的终止条件应该是什么?_Python_Algorithm - Fatal编程技术网

Python 15个谜题的这个实现的终止条件应该是什么?

Python 15个谜题的这个实现的终止条件应该是什么?,python,algorithm,Python,Algorithm,我正在尝试实现一个解决方案,用于在Python中输出一个问题的移动序列。这是MOOC可选作业的一部分。问题陈述在中给出 我有一个执行有效转换的程序版本(如下所示) 我首先识别空单元格的邻居(由0表示)并将它们放入列表中。然后,我从列表中随机选择一个邻居来执行与空单元格的交换。所有的掉期都被累积在一个不同的列表中,以记录解谜的动作顺序。然后在程序结束时输出 然而,用空单元格进行交换的随机数字选择只是永远在进行。为了避免循环的“无限”(非常长的周期),我现在将交换的数量限制为30 from rand

我正在尝试实现一个解决方案,用于在Python中输出一个问题的移动序列。这是MOOC可选作业的一部分。问题陈述在中给出

我有一个执行有效转换的程序版本(如下所示)

我首先识别空单元格的邻居(由0表示)并将它们放入列表中。然后,我从列表中随机选择一个邻居来执行与空单元格的交换。所有的掉期都被累积在一个不同的列表中,以记录解谜的动作顺序。然后在程序结束时输出

然而,用空单元格进行交换的随机数字选择只是永远在进行。为了避免循环的“无限”(非常长的周期),我现在将交换的数量限制为30

from random import randint
def find_idx_of_empty_cell(p):
    for i in range(len(p)):
        if p[i] == 0:
            return i

def pick_random_neighbour_idx(neighbours_idx_list):
    rand_i = randint(0, len(neighbours_idx_list)-1)
    return neighbours_idx_list[rand_i]

def perform__neighbour_transposition(p, tar_idx, src_idx):
    temp = p[tar_idx]
    p[tar_idx] = p[src_idx]
    p[src_idx] = temp

def solve_15_puzzle(p):
    standard_perm = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]
    neighbours_idx_list = []
    moves_sequence = []
    empty_cell_idx = find_idx_of_empty_cell(p)
    previous_empty_cell_idx = empty_cell_idx

    while (not(p == standard_perm) and len(moves_sequence) < 30):
        if not (empty_cell_idx in [0,4,8,12]):
            neighbours_idx_list.append(empty_cell_idx - 1)
        if not (empty_cell_idx in [3,7,11,15]):
            neighbours_idx_list.append(empty_cell_idx + 1)
        if not (empty_cell_idx in [0,1,2,3]):
            neighbours_idx_list.append(empty_cell_idx - 4)
        if not (empty_cell_idx in [12,13,14,15]):
            neighbours_idx_list.append(empty_cell_idx + 4)

        if previous_empty_cell_idx in neighbours_idx_list:
            neighbours_idx_list.remove(previous_empty_cell_idx)

        chosen_neighbour_idx = pick_random_neighbour_idx(neighbours_idx_list)
        moves_sequence.append(p[chosen_neighbour_idx])
        perform__neighbour_transposition(p, empty_cell_idx, chosen_neighbour_idx)
        previous_empty_cell_idx = empty_cell_idx
        empty_cell_idx = chosen_neighbour_idx
        neighbours_idx_list = []

    if (p == standard_perm):
        print("Solution: ", moves_sequence)

15块瓷砖的问题更难,因为乍一看似乎更难

计算最佳(最短)解是一个困难的问题,已经证明,随着N的增加寻找最优解是NP困难的

找到(非最优)解决方案要容易得多。例如,一个非常简单的算法是:

  • 将当前位置的“距离”定义为每个磁贴距所需位置的距离之和
  • 从给定的位置开始,做一些随机移动
  • 如果移动后的距离提高或保持不变,则保留更改,否则撤消更改并返回起点
这种算法可以描述为一种多步骤随机爬山方法,能够解决15个难题(只需确保允许足够多的随机移动,以避开局部最小值)

Python可能不是解决这个问题的最佳语言,但是如果您使用PyPy实现,您可以在合理的时间内获得解决方案

我的实现为一个在几秒钟内被1000个随机移动混合在一起的谜题找到了解决方案,例如:

(1, 5, 43, [9, [4, 10, 14, 11, 15, 3, 8, 1, 13, None, 9, 7, 12, 2, 5, 6]])
(4, 17, 41, [9, [4, 10, 14, 11, 15, 3, 8, 1, 12, None, 6, 2, 5, 13, 9, 7]])
(7, 19, 39, [11, [4, 10, 14, 11, 15, 3, 1, 2, 12, 6, 8, None, 5, 13, 9, 7]])
(9, 54, 36, [5, [4, 14, 3, 11, 15, None, 10, 2, 12, 6, 1, 8, 5, 13, 9, 7]])
(11, 60, 34, [10, [4, 14, 3, 11, 15, 10, 1, 2, 12, 6, None, 8, 5, 13, 9, 7]])
(12, 93, 33, [14, [4, 14, 11, 2, 15, 10, 3, 8, 12, 6, 1, 7, 5, 13, None, 9]])
(38, 123, 31, [11, [4, 14, 11, 2, 6, 10, 3, 8, 15, 12, 1, None, 5, 13, 9, 7]])
(40, 126, 30, [13, [15, 6, 4, 2, 12, 10, 11, 3, 5, 14, 1, 8, 13, None, 9, 7]])
(44, 172, 28, [10, [15, 4, 2, 3, 12, 6, 11, 8, 5, 10, None, 14, 13, 9, 1, 7]])
(48, 199, 23, [11, [15, 6, 4, 3, 5, 12, 2, 8, 13, 10, 11, None, 9, 1, 7, 14]])
(61, 232, 22, [0, [None, 15, 4, 3, 5, 6, 2, 8, 1, 12, 10, 14, 13, 9, 11, 7]])
(80, 276, 20, [10, [5, 15, 4, 3, 1, 6, 2, 8, 13, 10, None, 7, 9, 12, 14, 11]])
(105, 291, 19, [4, [9, 1, 2, 4, None, 6, 8, 7, 5, 15, 3, 11, 13, 12, 14, 10]])
(112, 313, 17, [9, [1, 6, 2, 4, 9, 8, 3, 7, 5, None, 14, 11, 13, 15, 12, 10]])
(113, 328, 16, [15, [1, 6, 2, 4, 9, 8, 3, 7, 5, 15, 11, 10, 13, 12, 14, None]])
(136, 359, 15, [4, [1, 6, 2, 4, None, 8, 3, 7, 9, 5, 11, 10, 13, 15, 12, 14]])
(141, 374, 12, [15, [1, 2, 3, 4, 8, 6, 7, 10, 9, 5, 12, 11, 13, 15, 14, None]])
(1311, 385, 11, [14, [1, 2, 3, 4, 8, 5, 7, 10, 9, 6, 11, 12, 13, 15, None, 14]])
(1329, 400, 10, [13, [1, 2, 3, 4, 6, 8, 7, 10, 9, 5, 11, 12, 13, None, 15, 14]])
(1602, 431, 9, [4, [1, 2, 3, 4, None, 6, 8, 7, 9, 5, 11, 10, 13, 15, 14, 12]])
(1707, 446, 8, [5, [1, 2, 3, 4, 6, None, 7, 8, 9, 5, 15, 12, 13, 10, 14, 11]])
(1711, 475, 7, [12, [1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 15, 12, None, 13, 14, 11]])
(1747, 502, 6, [8, [1, 2, 3, 4, 6, 5, 7, 8, None, 9, 10, 12, 13, 14, 15, 11]])
(1824, 519, 5, [14, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, 15, 12, 13, 14, None, 11]])
(1871, 540, 4, [10, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, None, 12, 13, 14, 15, 11]])
(28203, 555, 3, [9, [1, 2, 3, 4, 5, 6, 7, 8, 9, None, 10, 12, 13, 14, 11, 15]])
(28399, 560, 2, [10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 12, 13, 14, 11, 15]])
(28425, 581, 1, [11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, None, 13, 14, 15, 12]])
(28483, 582, 0, [15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, None]])
最后一行表示在24483次实验后,它在582次移动后找到了目标位置。请注意,582肯定远远不是最佳的,因为众所周知,在经典版的15个拼图中,没有位置需要超过80个动作

移动次数后的数字是“曼哈顿距离”,例如,最后第四行是位置:


其中,与解决方案的曼哈顿距离之和为3。

请为此问题创建一个标签“15拼图”。我认为这是必需的,但我没有这样做的必要特权。15个拼图有
(4*4)/2
(即10461394944000)有效配置;只是随机行走,等待在解决方案中绊倒,这将需要一段时间:-)。。。还请注意,“最困难”的配置至少需要80次单次交换移动到solve@6502这似乎是大海捞针。我该怎么做呢?补充了一个解释;不发布代码,因为这是一个有趣的实验;-)我理解你解决这个难题的策略的本质。不过,我不知道曼哈顿距离是多少,也不知道如何计算。在稍后的某个时候再次尝试这个谜题之前,我会对它做一些研究。为什么说Python不适合解决这个问题?我听说它是当今使用的最强大的语言之一。@flamingo_stark:Manhattan距离就是
abs(x1-x2)+abs(y1-y2)
。Python是一个非常非常好的语言(我喜欢它),但是缺省实现cpython并不炫耀执行速度,你应该考虑,例如,对于数字和数组操作的一般低级算法来说,它是C的100倍慢。PyPy实现将其提升到Javascript级别,虽然仍然比C慢,但速度要快得多。
(1, 5, 43, [9, [4, 10, 14, 11, 15, 3, 8, 1, 13, None, 9, 7, 12, 2, 5, 6]])
(4, 17, 41, [9, [4, 10, 14, 11, 15, 3, 8, 1, 12, None, 6, 2, 5, 13, 9, 7]])
(7, 19, 39, [11, [4, 10, 14, 11, 15, 3, 1, 2, 12, 6, 8, None, 5, 13, 9, 7]])
(9, 54, 36, [5, [4, 14, 3, 11, 15, None, 10, 2, 12, 6, 1, 8, 5, 13, 9, 7]])
(11, 60, 34, [10, [4, 14, 3, 11, 15, 10, 1, 2, 12, 6, None, 8, 5, 13, 9, 7]])
(12, 93, 33, [14, [4, 14, 11, 2, 15, 10, 3, 8, 12, 6, 1, 7, 5, 13, None, 9]])
(38, 123, 31, [11, [4, 14, 11, 2, 6, 10, 3, 8, 15, 12, 1, None, 5, 13, 9, 7]])
(40, 126, 30, [13, [15, 6, 4, 2, 12, 10, 11, 3, 5, 14, 1, 8, 13, None, 9, 7]])
(44, 172, 28, [10, [15, 4, 2, 3, 12, 6, 11, 8, 5, 10, None, 14, 13, 9, 1, 7]])
(48, 199, 23, [11, [15, 6, 4, 3, 5, 12, 2, 8, 13, 10, 11, None, 9, 1, 7, 14]])
(61, 232, 22, [0, [None, 15, 4, 3, 5, 6, 2, 8, 1, 12, 10, 14, 13, 9, 11, 7]])
(80, 276, 20, [10, [5, 15, 4, 3, 1, 6, 2, 8, 13, 10, None, 7, 9, 12, 14, 11]])
(105, 291, 19, [4, [9, 1, 2, 4, None, 6, 8, 7, 5, 15, 3, 11, 13, 12, 14, 10]])
(112, 313, 17, [9, [1, 6, 2, 4, 9, 8, 3, 7, 5, None, 14, 11, 13, 15, 12, 10]])
(113, 328, 16, [15, [1, 6, 2, 4, 9, 8, 3, 7, 5, 15, 11, 10, 13, 12, 14, None]])
(136, 359, 15, [4, [1, 6, 2, 4, None, 8, 3, 7, 9, 5, 11, 10, 13, 15, 12, 14]])
(141, 374, 12, [15, [1, 2, 3, 4, 8, 6, 7, 10, 9, 5, 12, 11, 13, 15, 14, None]])
(1311, 385, 11, [14, [1, 2, 3, 4, 8, 5, 7, 10, 9, 6, 11, 12, 13, 15, None, 14]])
(1329, 400, 10, [13, [1, 2, 3, 4, 6, 8, 7, 10, 9, 5, 11, 12, 13, None, 15, 14]])
(1602, 431, 9, [4, [1, 2, 3, 4, None, 6, 8, 7, 9, 5, 11, 10, 13, 15, 14, 12]])
(1707, 446, 8, [5, [1, 2, 3, 4, 6, None, 7, 8, 9, 5, 15, 12, 13, 10, 14, 11]])
(1711, 475, 7, [12, [1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 15, 12, None, 13, 14, 11]])
(1747, 502, 6, [8, [1, 2, 3, 4, 6, 5, 7, 8, None, 9, 10, 12, 13, 14, 15, 11]])
(1824, 519, 5, [14, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, 15, 12, 13, 14, None, 11]])
(1871, 540, 4, [10, [1, 2, 3, 4, 9, 6, 7, 8, 5, 10, None, 12, 13, 14, 15, 11]])
(28203, 555, 3, [9, [1, 2, 3, 4, 5, 6, 7, 8, 9, None, 10, 12, 13, 14, 11, 15]])
(28399, 560, 2, [10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, None, 12, 13, 14, 11, 15]])
(28425, 581, 1, [11, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, None, 13, 14, 15, 12]])
(28483, 582, 0, [15, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, None]])