Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.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求解_Python_Algorithm - Fatal编程技术网

锤子手表拼图;用Python求解

锤子手表拼图;用Python求解,python,algorithm,Python,Algorithm,所以,我妻子在蒸汽机上玩锤子手表。她遇到了一个难题,我决定尝试为她设计一个解决方案 下面是谜题的工作原理: 激活开关可以打开或关闭该开关,也可以切换其相邻的开关。 以下是游戏中的拼图游戏的YouTube视频: 我弄明白了如何让拼图的机制正常工作。我最终意识到我有两个选择让电脑解决这个问题: A)允许计算机通过随机选择开关进行求解 …或… B)创建一种算法,使计算机能够更有效地解决难题。 作为一名新程序员(代码学院教程,LPTHW课程,以及麻省理工学院edX计算机科学Python课程),我觉

所以,我妻子在蒸汽机上玩锤子手表。她遇到了一个难题,我决定尝试为她设计一个解决方案

下面是谜题的工作原理:
激活开关可以打开或关闭该开关,也可以切换其相邻的开关。

以下是游戏中的拼图游戏的YouTube视频:


我弄明白了如何让拼图的机制正常工作。我最终意识到我有两个选择让电脑解决这个问题:

A)允许计算机通过随机选择开关进行求解
…或…
B)创建一种算法,使计算机能够更有效地解决难题。

作为一名新程序员(代码学院教程,LPTHW课程,以及麻省理工学院edX计算机科学Python课程),我觉得自己的能力有点有限。我是来学习的!请帮忙

请帮助: 我需要帮助,或者想出一个更好的方法来随机解决这个问题,或者更好,有一个算法,让计算机系统地解决这个难题

我能做的唯一一件事就是让计算机将拼图的状态存储在列表或字典中,通过跳过这些存储的状态来帮助程序找到新的可能的解决方案

当前程序的工作原理: 我打算允许用户使用前9个原始输入输入输入拼板的当前状态。然后它进入一个循环,随机切换拼图板的开关,直到它们全部打开

注:当我注册一个StackOverflow帐户并键入此消息时,我的计算机一直在后台运行此程序以找到解决方案。已经一个小时了,仍然没有找到解决方案,目前正在进行第9200000次迭代。我认为它不起作用


首先,您只设置了一次ans。您需要在循环中对其进行评估。(尽管这可能是由于模切压痕造成的)。这可能就是你目前的方法没有完成的原因

另一方面,更“自然”的表示可能是使用布尔数组(甚至是0-511之间的数字),这样switcheroo就变成了

a1 = not a1
另外,随机方法会给你大量的打字工作。我想您应该从从解决方案到当前配置的角度来考虑这一点。把它想象成一个迷宫。有2^9=512个可能的配置(或迷宫中的位置)。每次你按下开关就像在迷宫中迈出一步。现在,您真正想要的是找到从初始配置到解决方案的最短路径。看看Dijkstra的算法:

我想你应该能想出一个算法。不应该太难

首先,没有必要按下任何开关一次以上。因为第二次只会取消您对第一次点击所做的操作,并返回到初始状态(无论您同时对其他开关所做的操作)

那我们打电话吧

A11, A12, A13
A21, A22, A23
A31, A32, A33
启动时开关的状态

使用相同的坐标系,我们用T表示接触的次数。 根据我们前面所说的,每个T要么是0,要么是1

如果你能做一点数学,并且你知道代数,在一个值只取0或1的域中进行运算,那么我认为你应该能够通过以下方法将问题简化为该空间中的问题:

A11 + T11 + T12 + T21 = 1
A12 + T11 + T12 + T13 + T22 = 1
A13 + T12 + T13 + T23 = 1
...
如果你把它作为矩阵运算,你可能只需要将一个矩阵求逆,然后根据矩阵运算找到Ts


也许这更适合于另一个比Stackoverflow更注重数学的站点…

有一种众所周知的方法可以解决这个问题。设x_1,…,x_n为变量,对应于是否作为解决方案的一部分按下第n个按钮,并设a_1,…,a_n为初始状态

假设您正在解决一个3x3问题,变量设置如下:

x_1 x_2 x_3
x_4 x_5 x_6
x_7 x_8 x_9
这个初始状态是:

a_1 a_2 a_3
a_4 a_5 a_6
a_7 a_8 a_9
现在,你可以写下解必须满足的一些方程(以算术模2表示)。它基本上是编码关于哪些开关导致特定灯光切换的规则

a_1 = x_1 + x_2 + x_4
a_2 = x_1 + x_2 + x_3 + x_5
...
a_5 = x_2 + x_4 + x_5 + x_6 + x_8
...
a_9 = x_6 + x_8 + x_9
现在你可以用高斯消去法来解这组联立方程。因为你在做算术模2,它实际上比实数上的联立方程要简单一些。例如,要去掉第二个方程中的x_1,只需将第一个方程添加到其中

a_1 + a_2 = (x_1 + x_2 + x_4) + (x_1 + x_2 + x_3 + x_5) = x_3 + x_4 + x_5
具体来说,这里是算术模2中的高斯消去算法:

  • 选择一个包含x_1的方程式。命名为E_1
  • 将E_1添加到每一个包含x_1的未命名方程式中
  • 对x_2,x_3,…,x_n重复上述步骤
现在,E_n是一个只包含x_n的方程。您可以将从中得到的x_n值代入前面的方程式中。对E_{n-1},…,E_1重复上述步骤

总的来说,这解决了O(n^3)操作中的问题

这里有一些代码

class Unsolvable(Exception):
    pass

def switches(n, m, vs):
    eqs = []
    for i in xrange(n):
        for j in xrange(m):
            eq = set()
            for d in xrange(-1, 2):
                if 0 <= i+d < n: eq.add((i+d)*m+j)
                if d != 0 and 0 <= j+d < m: eq.add(i*m+j+d)
            eqs.append([vs[i][j], eq])

    N = len(eqs)
    for i in xrange(N):
        for j in xrange(i, N):
            if i in eqs[j][1]:
                eqs[i], eqs[j] = eqs[j], eqs[i]
                break
        else:
            raise Unsolvable()
        for j in xrange(i+1, N):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]

    for i in xrange(N-1, -1, -1):
        for j in xrange(i):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]
    return [(i//m,i%m) for i, eq in enumerate(eqs) if eq[0]]

print switches(4, 3, ([1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]))
类无法解决(例外):
通过
def开关(n、m、vs):
方程=[]
对于x范围内的i(n):
对于X范围内的j(m):
eq=set()
对于X范围内的d(-1,2):

如果这个游戏通常被称为0,我认为标记为dupe的问题没有一个好的答案。最重要的答案是3个链接,其中一个已断开。这两个好的链接是长PDF,在其中我找不到线性代数解决方案的清晰描述。我将我的答案复制到了原始问题。我认为这比重新打开这个要好。显然,还有一个游戏玩家的方法叫“chase the lights:”这是一个3x3 board的Python示例(最大迭代次数似乎是13次):这里还有一个很好的JavaScript解算器:
class Unsolvable(Exception):
    pass

def switches(n, m, vs):
    eqs = []
    for i in xrange(n):
        for j in xrange(m):
            eq = set()
            for d in xrange(-1, 2):
                if 0 <= i+d < n: eq.add((i+d)*m+j)
                if d != 0 and 0 <= j+d < m: eq.add(i*m+j+d)
            eqs.append([vs[i][j], eq])

    N = len(eqs)
    for i in xrange(N):
        for j in xrange(i, N):
            if i in eqs[j][1]:
                eqs[i], eqs[j] = eqs[j], eqs[i]
                break
        else:
            raise Unsolvable()
        for j in xrange(i+1, N):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]

    for i in xrange(N-1, -1, -1):
        for j in xrange(i):
            if i in eqs[j][1]:
                eqs[j][0] ^= eqs[i][0]
                eqs[j][1] ^= eqs[i][1]
    return [(i//m,i%m) for i, eq in enumerate(eqs) if eq[0]]

print switches(4, 3, ([1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]))