我刚刚回答了这个问题,但它被错误地迁移到另一个 stackexchange 站点:https://codegolf.stackexchange.com/questions/3019/getting-an-answer-from-a-string-of-digits/3027#3027
这种运动有分类吗? (例如子集和等)
我称之为查找列表的所有二元运算符“减少”,以任意顺序应用,运算符 +、-、*、/ 和 10a+b/@ 987654329@
这是 python 中的一种蛮力方法。在下面树中的每个节点处,取左右可能性的笛卡尔积。对于每一对,将所有运算符应用于它,以产生一组新的可能性。你要小心不要做(1-2)3 = -13;您可以通过创建 Digit 对象来解决此问题。
下面是加泰罗尼亚数字的说明,其中每个节点都是一个运算符。操作数大约为Catalan(#digits-1) * #operators^(#digits-1)。如果#digits=10,那么它应该只有大约十亿次尝试。
使用How to print all possible balanced parentheses for an expression?我们可以写:
#!/usr/bin/python3
import operator as op
from fractions import Fraction
Fraction.__repr__ = lambda self: '{}/{}'.format(self.numerator, self.denominator)
Digits = tuple
operators = {op.add, op.sub, op.mul, Fraction}
def digitsToNumber(digits):
"""
(1,2,3) -> 123
123 -> 123
"""
if isinstance(digits, Digits):
return sum(d * 10**i for i,d in enumerate(reversed(digits)))
else: # is int or float
return digits
def applyOperatorsToPossibilities(left, right):
"""
Takes every possibility from the left, and every
possibility from the right, and takes the Cartesian
product. For every element in the Cartesian product,
applies all allowed operators.
Returns new set of merged possibilities, ignoring duplicates.
"""
R = set() # subresults
def accumulate(n):
if digitsToNumber(n)==TO_FIND:
raise Exception(n)
else:
R.add(n)
for l in left:
for r in right:
if isinstance(l, Digits) and isinstance(r, Digits):
# (1,2),(3) --> (1,2,3)
accumulate(l+r)
for op in operators:
# 12,3 --> 12+3,12-3,12*3,12/3
l = digitsToNumber(l)
r = digitsToNumber(r)
try:
accumulate(op(l,r))
except ZeroDivisionError:
pass
return R
def allReductions(digits):
"""
allReductions([1,2,3,4])
[-22, -5, -4, -3, -5/2, -1/1, -1/3, 0, 1/23, 1/6, 1/5, 1/3, 2/3, 1/1, 3/2, 5/3, 2, 7/2, 4/1, 5, 6, 7, 9, 15, 23, 24, 36, 123]
"""
for reduction in set.union(*associations(
digits,
grouper=applyOperatorsToPossibilities,
lifter=lambda x:{(x,)})
):
yield digitsToNumber(reduction)
TO_FIND = None
INPUT = list(range(1,4))
print(sorted(allReductions(INPUT)))