对于大约 6 位左右的数字,我会根据以下方案说暴力破解:
1)将您的初始值拆分为一个数字列表(数组,无论如何,根据语言)。最初,这些是数字。
2) 对于每对数字,使用其中一个运算符将它们组合在一起。如果结果是目标数字,则返回成功(并打印出您退出时执行的所有操作)。否则,如果它是一个整数,则在新的、较小的列表上递归,该列表由您刚刚计算的数字和您未使用的数字组成。或者您可能希望允许非整数中间结果,这将使搜索空间更大一些。二进制操作是:
- 添加
- 减去
- 乘
- 划分
- 力量
- 连接(只能用于原始数字或连接产生的数字)。
3) 允许平方根会使搜索空间膨胀到无穷大,因为它是一元运算符。所以你需要一种方法来限制它可以应用的次数,我不确定那会是什么(答案接近 1 时精度损失,也许?)。这是只允许整数中间值的另一个原因。
4) 求幂会迅速导致溢出。2^(9^(4^8)) 太大而无法直接存储所有数字[尽管在基数 2 中它们是什么很明显;-)]。因此,您要么必须接受您可能会错过具有较大中间值的解决方案,否则您将不得不编写一堆代码来根据因子进行算术运算。这些显然不能很好地与加法交互,因此您可能需要进行一些估计。例如,仅通过查看因子数量的大小,我们发现 2^(9^(4^8)) 与 (2^35) 相去甚远,因此无需计算 (2^(9^( 4^8)) + 5) / (2^35)。它不可能是 29485235,即使它是一个整数(它肯定不是 - 另一种排除这个特定示例的方法)。
5)我忘记排除任何输入的简单解决方案,即连接所有数字。不过,这很容易处理,只需通过递归维护一个参数,该参数告诉您是否在通往当前子问题的路由上执行了任何非串联操作。如果没有,请忽略错误匹配。
我对 6 位数的估计是基于这样一个事实,即即使没有解决方案,也很容易编写一个在几分之一秒内运行的倒计时求解器。这个问题的不同之处在于数字必须按顺序使用,但操作更多(Countdown 不允许求幂、平方根或连接,或非整数中间结果)。总的来说,我认为这个问题是可比的,只要你解决了平方根和溢出问题。如果您可以在几分之一秒内解决一个案例,那么您可以在合理的时间内通过一百万个候选人强行闯关(假设您不介意让您的 PC 开机)。
10 位数,蛮力似乎是不可能的,因为你必须考虑 100 亿个案例,每个案例都需要大量的递归。所以我猜你会在两者之间的某个地方达到蛮力的极限。
另请注意,我在顶部的简单算法仍然有很多冗余 - 它不会阻止您执行 (4,7,9,1) -> (47,9,1) -> (47,91),并且然后再做 (4,7,9,1) -> (4,7,91) -> (47,91)。因此,除非您弄清楚这些重复将在哪里发生并避免它们,否则您将尝试 (47,91) 两次。显然,当列表中只有 2 个数字时,这并没有太多工作,但是当列表中有 7 个数字时,您可能不想以 6 种不同的方式将其中的 4 个加在一起,然后解决由此产生的 4 数字问题 6次。倒计时游戏不需要聪明,但据我所知,在这个问题中,它可能会在暴力破解 8 位数字和暴力破解 9 位数字之间产生差异,这非常重要。