解决Python问题

时间:2020-07-15 10:08:24

标签: python python-3.x

我目前有以下两项,都必须为true:

A B C D + A E F = E F G H和

I C J * E = A B C D

每个字母代表一个从0到9的唯一数字,并且两个等式都必须成立。 我需要编写一个输出正确答案的Python解决方案,这是我的代码:

import numpy as np

def solve():
    for a in range(0,10):
        for b in range(0,10):
            for c in range(0,10):
                for d in range(0,10):
                    for e in range(0,10):
                        for f in range(0,10):
                            for g in range(0,10):
                                for h in range(0,10):
                                    for i in range(0,10):
                                        for j in range(0,10):
                                            if len(set([a, b, c, d, e, f, g, h, i, j])) == 10:
                                                icj = 100*i + 10*c + j
                                                e = e
                                                abcd = 1000*a + 100*b + 10*c + d
                                                aef = 100*a + 10*e + f
                                                efgh = 1000*e + 100*f + 10*g + h
                                                if icj * e == abcd and abcd + aef == efgh:
                                                    print(icj, e, abcd, aef, efgh)
print(solve())                                               

但是,当我运行此命令时,不仅需要花一些时间才能运行,而且还会输出“无”。关于我要去哪儿有什么想法吗?

2 个答案:

答案 0 :(得分:4)

您应该尝试使用for x in range(0, 10)而不是for x in range(0,9),因为您是从0循环到8。

如果您想以更有效的方式循环,则可以使用permutations

from itertools import permutations
for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
    print(a, b, c, d, e, f, g, h, i, j)

结果:

0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 9 8
...
9 8 7 6 5 4 3 2 0 1
9 8 7 6 5 4 3 2 1 0

这是最终代码:

import numpy as np
from itertools import permutations

def solve():
    for a, b, c, d, e, f, g, h, i, j in permutations(range(0, 10), 10):
        icj = 100*i + 10*c + j
        e = e
        abcd = 1000*a + 100*b + 10*c + d
        aef = 100*a + 10*e + f
        efgh = 1000*e + 100*f + 10*g + h
        if icj * e == abcd and abcd + aef == efgh:
            print(icj, e, abcd, aef, efgh)
            print(a, b, c, d, e, f, g, h, i, j)

solve()

输出:

934 7 6538 672 7210
6 5 3 8 7 2 1 0 9 4

答案 1 :(得分:1)

除错别字外,如果仅在内部循环中测试所有10位数字是否都不同,则此内部循环将执行10 10 = 10,000,000,000次。如果您每次通过测试,则“仅”需要10个! = 3,628,800传递到此内部循环。

您仍然可以更好地更改变量的顺序,因此可以测试方程式abc * d == hibj,而无需其他三个变量,只有等式成立时,它才能更深入。对于这7位数字,您在该循环中输入604,800次,而只需要更深入45次即可到达最内部的循环,仅270次。

def solve():
    for a in range(0, 10):
        for b in range(0, 10):
            if a != b:
                for c in range(0, 10):
                    if not c in [a, b]:
                        for d in range(0, 10):
                            if not d in [a, b, c]:
                                for h in range(0, 10):
                                    if not h in [a, b, c, d]:
                                        for i in range(0, 10):
                                            if not i in [a, b, c, d, h]:
                                                for j in range(0, 10):
                                                    if not j in [a, b, c, d, h, i]:
                                                        abc = 100 * a + 10 * b + c
                                                        hibj = 1000 * h + 100 * i + 10 * b + j
                                                        if abc * d == hibj:
                                                            print(abc, '*', d, '=', hibj)
                                                            for e in range(0, 10):
                                                                if not e in [a, b, c, d, h, i, j]:
                                                                    for f in range(0, 10):
                                                                        if not f in [a, b, c, d, h, i, j, e]:
                                                                            for g in range(0, 10):
                                                                                if not g in [a, b, c, d, h, i, j, e, f]:
                                                                                    hde = 100 * h + 10 * d + e
                                                                                    defg = 1000 * d + 100 * e + 10 * f + g
                                                                                    if hibj + hde == defg:
                                                                                        print(abc, d, hibj, hde, defg)

solve()
print('done')

尽管它现在可以运行得足够快,但是可以考虑更具体的优化:

  • 将顺序更改为a,b,ch,i,j,然后计算hibj是否为abc的倍数。仅在情况允许的情况下,此定义d应该在09之间,并且与其他地方不同。
  • 或者相反:生成a,b,c,d,然后首先尝试所有倍数是否适合b,然后尝试相应的h,i,j是否彼此不同且与{{1 }}。
  • a,b,c,d应该小于h,否则a将大于d。这使得9至少a
  • 通常在这种问题中,每个数字的第一位数字应假定为非零,这可以进一步减少支票的数量。

另一种方法是使用SMT/SAT之类的Z3求解器。使用这样的求解器,可以制定所有条件,并通过各种试探法寻找解决方案。示例代码:herehere

这是代码的样子:

1

这将打印出from z3 import Int, And, Or, Distinct, Solver, sat D = [Int(f'{c}') for c in "abcdefghij"] a, b, c, d, e, f, g, h, i, j = D vals_0_to_9 = [And(Di >= 0, Di <= 9) for Di in D] all_different = [Distinct(D)] abc = 100 * a + 10 * b + c hibj = 1000 * h + 100 * i + 10 * b + j hde = 100 * h + 10 * d + e defg = 1000 * d + 100 * e + 10 * f + g equations = [abc * d == hibj, hibj + hde == defg] s = Solver() s.add(vals_0_to_9 + all_different + equations) while s.check() == sat: m = s.model() print(", ".join([f'{Di}={m[Di]}' for Di in D])) s.add(Or([Di != m[Di] for Di in D])) 作为唯一解决方案。