解决这个矩阵拼图的更有效的解决方案?

时间:2016-08-17 17:44:15

标签: python matrix puzzle

找到3x3矩阵M,其行,列和对角线总计为15.条件:您必须使用1-9中的每个数字。

我不是很聪明,所以我只是尝试了这种蛮力方法:

date

它有效,但效率不高。任何人都可以帮我找到更有效的解决方案吗?

4 个答案:

答案 0 :(得分:3)

很容易。试想有多少种方法可以构建三个数字中的15个。

1+5+9, 1+6+8, 2+4+9, 2+5+8, 2+6+7, 3+4+8, 3+5+7, 4+5+6

每个总和出现在你的广场上,因为只有8种方式。 5必须在中心,因为它出现4次。 2,4,6,8必须在角落,因为它们出现了3次。

继续,你只需要思考即可找到解决方案。

答案 1 :(得分:1)

您将获得的最大加速来自生成方块,以便它们已经是唯一的。最简单的方法是itertools.permutations。这将减少你检查9! == 362880板而不是387420489板(约为工作的1/1000),您无需检查以确保它们是唯一的。

from itertools import permutations
t1=time()
for board in permutations(list(range(1,10)),9):
    if sum(board[0:3]) == 15:
        if sum(board[3:6])== 15:
            if board[0]+board[3]+board[6]==15:
                if board[1]+board[4]+board[7]==15:
                    if board[0]+board[4]+board[8]==15:
                        if board[2]+board[4]+board[6]==15:
                            print(board[0:3])
                            print(board[3:6])
                            print(board[6:9])
                            break

这个解决方案的一个主要问题是我们仍在检查比我们需要的更多的案例。需要注意的是,对于每个(a,b,d,e),c,f,g,h和i中的每一个都存在最多1个值。这意味着我们只需检查9P4 == 3024种可能性。这样做的缺点是我们不能保证所有的价值都是独一无二的。但即使我们添加了这些检查,我们仍然可以看到比我们更简单的代码快10倍的速度。

def solve_999():
    for a,b,d,e in permutations(range(1,10),4):
        c = 15 - (a + b)
        f = 15 - (d + e)
        g = 15 - (a + d)
        h = 15 - (b + e)
        i = 15 - (a + e)
        if 15 == g+h+i == c+f+i == c+e+g:
            if len(set([a,b,c,d,e,f,g,h,i]))==9:
                 print(a, b, c)
                 print(d, e, f)
                 print(g, h, i)
                 print()
                 break

为代码计时:

from timeit import timeitrom itertools import permutations
def solve_999():
    for a,b,d,e in permutations(range(1,10),4):
        c = 15 - (a + b)
        f = 15 - (d + e)
        g = 15 - (a + d)
        h = 15 - (b + e)
        i = 15 - (a + e)
        if 15 == g+h+i == c+f+i == c+e+g:
            if len(set([a,b,c,d,e,f,g,h,i]))==9:
                return
print(timeit(solve_999, number=1000))

产生2.9秒/ 10000次尝试的时间== .00029秒/尝试

答案 2 :(得分:1)

比其他人短:

>>> from itertools import permutations
>>> for a, b, c, d, e, f, g, h, i in permutations(range(1, 10)):
        if 15 == a+b+c == d+e+f == a+d+g == b+e+h == a+e+i == c+e+g:
            print(a, b, c)
            print(d, e, f)
            print(g, h, i)
            break

2 7 6
9 5 1
4 3 8

在我的电脑上搜索大约需要0.009秒。测量如下,进行1000次需要大约9秒钟:

from itertools import permutations
from timeit import timeit

def solve_999():
    for a, b, c, d, e, f, g, h, i in permutations(range(1, 10)):
        if 15 == a+b+c == d+e+f == a+d+g == b+e+h == a+e+i == c+e+g:
            return

print(timeit(solve_999, number=1000))

答案 3 :(得分:0)

您可以使用itertools.permutations库来迭代检查所需总和的所有可能性。

虽然您的代码适用于固定大小的输入数组(在本例中为3x3 = 9),但我已将其概括为检查通过使用某些python辅助拼接提供的任何范围内的任何给定总和。请注意,输入的长度需要是一个完美的正方形才能实现。

from itertools import permutations
from math import sqrt

def check_magic_square(rangeallowed,sumMS):
    sidelenght = int(sqrt(len(rangeallowed)))
    for i in permutations(rangeallowed):
        # initialize all conditions to be satisfied
        MSConditionsSatisfied = True
        # Check for forward diagonal sum
        if (MSConditionsSatisfied and sum(i[::sidelenght+1]) != sumMS): MSConditionsSatisfied = False
        # Check for reverse diagonal sum
        if (MSConditionsSatisfied and sum(i[sidelenght-1:-1:sidelenght-1]) != sumMS): MSConditionsSatisfied = False
        for j in range(sidelenght):
            # Check for each column
            if (MSConditionsSatisfied and sum(i[j::sidelenght]) != sumMS): MSConditionsSatisfied = False
            # Check for each row
            if (MSConditionsSatisfied and sum(i[j*sidelenght:(j+1)*sidelenght]) != sumMS): MSConditionsSatisfied = False
        # if all conditions are satisfied, return the splice reshaped to be a square matrix
        if MSConditionsSatisfied: return [[i[k*sidelenght + j] for j in range(sidelenght)] for k in range(sidelenght)]
    return False

if __name__ == "__main__":
    print(check_magic_square(range(1,10),15))

返回

  

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

我的i5机器上的时间为0.1秒