【问题标题】:How to solve this problem without brut-forcing and/or having a huge computation time?如何在不使用暴力和/或计算时间过长的情况下解决这个问题?
【发布时间】:2019-08-08 02:39:51
【问题描述】:

我正在尝试解决以下问题:

A store sells large individual wooden letters for signs to put on houses. 
The letters are priced individually.
The total cost of letters in LOAN is 17 dollars.
The total cost of letters in SAM is 18 dollars.
The total cost of letters in ANNA is 20 dollars.
The total cost of letters in ROLLO is 21 dollars.
The total cost of letters in DAMAGES is 30 dollars.
The total cost of letters in SALMON is 33 dollars.

How much would the letters in the name GARDNER cost?

我使用以下 python 代码强制字母成本,但需要数小时才能收敛,因为它们有 33^10 种可能的组合来测试。我使用 n=33,因为它是一个名称的最大成本,但实际上,n 可以减少到 15 甚至 10,但不会收敛。

def func(letters):
    print letters
    if letters['L']+letters['O']+letters['A']+letters['N'] != 17:
        return False
    elif letters['S']+letters['A']+letters['M'] != 18:
        return False
    elif 2*letters['A']+2*letters['N'] != 20:
        return False
    elif letters['R']+2*letters['O']+2*letters['L'] != 21:
        return False
    elif letters['D']+2*letters['A']+letters['M']+letters['G']+letters['E']+letters['S'] != 30:
        return False
    elif letters['S']+letters['A']+letters['L']+letters['M']+letters['O']+letters['N'] != 33:
        return False
    return True

def run(letters, n, forbidden_letters):
    for letter in letters.keys():
        if letter not in forbidden_letters:
            for i in range(1, n):
                letters[letter] = i
                if not func(letters):
                    if letter not in forbidden_letters:
                        forbidden_letters+=letter
                    if run(letters, n, forbidden_letters):
                        return letters
                else:
                    return letters

LETTERS = {
    "L":1,
    "O":1,
    "A":1,
    "N":1,
    "S":1,
    "M":1,
    "R":1,
    "D":1,
    "G":1,
    "E":1,
}
n=33
print run(LETTERS, n, "")

暴力破解最终会起作用,但它占用大量 CPU 资源,肯定不是最佳解决方案。

有没有人有更好的解决方案来解决这个问题?要么通过减少计算时间,要么通过良好的数学方法。

谢谢大家。

【问题讨论】:

  • 它是一个线性方程。

标签: python algorithm computation


【解决方案1】:

这就是所谓的线性方程组。如果需要,您可以手动求解,但也可以使用线性求解器。以 sympy 为例

import sympy

l,o,a,n,s,m,r,d,g,e = sympy.symbols('l,o,a,n,s,m,r,d,g,e')

eq1 = l+o+a+n - 17
eq2 = s+a+m -18
eq3 = a+n+n+a -20
eq4 = r+o+l+l+o -21 
eq5 = d+a+m+a+g+e+s -30
eq6 = s+a+l+m+o+n- 33

sol, = sympy.linsolve([eq1,eq2,eq3,eq4,eq5,eq6],(l,o,a,n,s,m,r,d,g,e))
l,o,a,n,s,m,r,d,g,e = sol

print(g+a+r+d+n+e+r)

线性方程的求解速度非常快。复杂度为 O(n3),其中 n 是变量的数量。因此,对于这样一个小问题,它几乎是即时的。

【讨论】:

  • 谢谢,我认为 10 个未知变量和只有 6 个方程不足以以这种方式求解。
  • 诚然,gardner 中的一些字母价格很奇怪,但它解析为一个数字。
  • 似乎有些字母值没有被解析(例如'o','m','g'或'e'),但是因为它们在'gardner'中相互减去名字...
  • 感谢您的解决方案,它确实解决了“gardner”名称的问题,但我们无法访问所有单独的字母值,无论如何它已经很好地解决了,我不知道他们是否是其他无需暴力破解即可访问所有值的方法
【解决方案2】:
L + O + A + N - 17 = 0
S + A + M - 18 = 0
2 * A  + 2 * N - 20 = 0

等等。

尝试制作如下矩阵:

 L O A N S M R D G E val
[1 1 1 1 0 0 0 0 0 0 -17 | 0] LOAN
[0 0 1 0 1 1 0 0 0 0 -18 | 0] SAM
[0 0 2 2 0 0 0 0 0 0 -20 | 0] ANNA
...
[0 0 1 1 0 0 2 1 1 2 -x | 0] GARDENER

现在您可以使用例如高斯方法来解决它。时间复杂度为 O(n^3)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    • 2023-02-25
    • 2017-05-23
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多