2018-02-28 董付国,胡凤国 Python小屋
问题描述:在123456789这9个数字中间插入任意多个+和-的组合,使得表达式的值为100,输出所有符合条件的表达式。
昨天发了一个暴力测试的方法来解决问题,详见Python查找所有类似于123-45-67+89 = 100的组合,但是暴力测试的方法非常慢,大概需要运行3个小时多。今天分享一个超高效的算法及其实现,可以瞬间输出所有结果,感谢中国传媒大学胡凤国老师提供这个神奇的算法。
主要思路:设计一个三进制加法算法,让8个0逐步变化到8个3,其中每一位上的数字可以是0、1、2,然后让0对应空格、1对应+、2对应-,然后在1到9之间的8个位置上分别插入空格、+或-符号,最后删掉表达式中的空格并求值,如果等于100则满足条件。
参考代码:
'''[0,0,0,0,0,0,0,0]->[0,0,0,0,0,0,0,1]->...[2,2,2,2,2,2,2,2]'''
def triAdd(operators):
lastPosition = len(operators)-1
c = 1
for i in range(lastPosition,-1,-1):
c , operators[i] = divmod(operators[i]+c,3) #进行求3模,得到c为商,operators[i]为余数
if c ==0: #保证triAdd函数从右至左,每次只对末位元素进行+1。
return None
return 1
def main(digits='123456789',total=100):
d = ' +-'
operators = [0]*(len(digits)-1)
while not triAdd(operators):
operator = map(lambda o:d[o],operators)
exp = ''.join((o+c for o,c in zip(digits,operator)))+digits[-1] #1-8后面分别按照o+c进行组合
exp = ''.join(exp.split())
if eval(exp) == total:
print(exp)
main()
结果如下: