所有可能的数字表达

时间:2013-01-13 23:34:30

标签: python combinatorics catalan

一个完全无用的问题:我买了一个数字游戏,它由两个黑色骰子和五个彩色骰子组成。两个黑色数字形成一个2位数字,范围从11到66,另外5个是您可以使用的数字,将它们与所有可能的数字表达式相结合,以获得目标数字。

例如,黑色40 + 2:目标42

有色5 3 6 2 4,你可以通过5 3 + 6 * 4 2 +获得目标 - (使用RPN,因为它避免使用括号)。

现在,当我们玩游戏时,我想用我的掌上电脑找到最佳答案。

我必须说我对解决方案并没有太多考虑,我只是寻找关于查找参数排列的部分,但是如何从中生成可能的表达式?我会使用RPN并枚举表达式的所有可能“形状”,然后使用+ - * /填充空白。

我不认识枚举表达式形状的问题。

输出将是这样的: ..... XXXX .... x.xxx ... x..xxx ..x ... XXX .... XX.XX ... x.x.xx ..x..x.xx ... xx..xx ..x.x..xx .... XXX.X ... x.xx.x ..x..xx.x ... xx.x.x ..x.x.x.x

像这样的事情: ..xx ... XX ... xxx..x ..x.xx..x ..x.xx..x 无效,因为第二个或第三个运算符会找到一个操作数。

我可以使用硬编码列表,但它看起来真的很难看!

2 个答案:

答案 0 :(得分:7)

我认为你正在寻找的是大小为5的完整二叉树的枚举。(这些对象的数量是第五个Catalan number,即14。)。根据加泰罗尼亚数字的标准递归,枚举是直截了当的:
http://upload.wikimedia.org/math/2/f/1/2f17435a71394ce667ab694b27341560.png
对于每个(i,5-i),生成具有i个叶子的所有树,并且所有具有5-i的树叶,并且对于每个树的每个组合,构造通过创建一个根节点来生成一棵新树,该根节点的左子节点来自第一组,右子节点来自第二组。如果您不想使用树,请直接使用RPN:

# Produces all possible RPN layouts with n values and n-1 binary operators,
# representing values as '#' and operators as '+'
def RPN(n):
  if n == 1:
    yield '#'
  for i in range(1,n):
    for left in RPN(i):
      for right in RPN(n - i):
        yield left + right + '+' 

当然,也有一元运营商。如果你允许这些,它会变得更复杂。

请注意,您可以直接调整以上内容直接插入参数;而不是将n分成(i,n-i),你会发现n个值集合的所有分区成为两个非空子集。 (否则,您可以找到该组数字的所有排列,并将它们插入到生成的RPN表达式中。)

然后你需要做的“全部”是插入所有可能的操作符序列(如果你只允许+, - ,*和/那么你有4个 4 = 256种可能性)。

因此,如果五个数字不同,那么最终会得到14 * 5! * 4 4 = 430080表达式进行测试。

答案 1 :(得分:0)

枚举不同数字块数的问题是您可以应用于集合http://en.wikipedia.org/wiki/Partition_of_a_set的分区数