解决具有多个答案的算术表达式(越南数学迷宫)

时间:2017-02-16 06:08:30

标签: prolog

我必须尝试使用​​prolog来解决这个越南数学挑战(https://www.theguardian.com/science/alexs-adventures-in-numberland/2015/may/20/can-you-do-the-maths-puzzle-for-vietnamese-eight-year-olds-that-has-stumped-parents-and-teachers)并且我对如何编写谓词感到非常难过。这是问题:

  

假设普通的算术优先规则(即   加/减之前的乘法/除法)。答案   应该是将要输入的数字列表的形式   迷宫中的空白从左到右。命名谓词mathmaze   并让它接受一个参数,它被实例化为正确的   数字列表(并在提示时给出其他答案;)。

这是我到目前为止所做的,但我不知道如何在等式的每个位置尝试1-9。

mathmaze([H|T]) :-
   A + ((13* B) / C) + D + (12 * E) - F - 11 + G * (H / I) - 10 = 66. 

2 个答案:

答案 0 :(得分:1)

mathmaze([A,B,C,D,E,F,G,H,I]) :-
    permutation([1,2,3,4,5,6,7,8,9], [A,B,C,D,E,F,G,H,I]),
    66 is (A + ((13 * B) / C) + D + (12 * E) - F - 11 + (G * (H / I)) - 10).

这说:

  • 列出9个变量
  • 使变量列表成为由1到9组成的列表的排列。
  • 检查变量是否评估(使用是)到66。

这可以使用CLPFD编写,但它不提供任何非整数除法,因此它将生成错误的答案,对于如此严格定义的问题,用all_distinct/1和{{替换排列3}}似乎不值得努力(但CLPFD对于这种问题通常是一个有用的库)。

答案 1 :(得分:1)

应用CLP(FD)约束

首先,一般说明:在Prolog中推理整数时,我强烈建议您使用系统的 CLP(FD)约束

正如@JimAshworth正确指出的那样,这样的约束仅适用于整数,特别是不提供 division 的小数结果。

然而,我们经常,在这种情况下,通过纯粹的代数转换,可以轻松绕过这种划分。

在这种情况下,我可以消除分裂

A/B #= C

只需写而不是

A #= B*C

代数上,我只是将方程的双方B相乘。

解决方案

因此,可能的解决方案可能如下所示:

mathmaze(Vs) :-
        Vs = [A,B,C,D,E,F,G,H,I],
        Vs ins 1..9,
        all_different(Vs),
          A*C*I + 13*B*I + D*C*I + 12*E*C*I
        - F*C*I - 11*C*I + G*C*H - 10*C*I #= 66*C*I.

示例查询和结果:

?- mathmaze(Vs), time(labeling([ff], Vs)).
% 5,869,675 inferences, 7.221 CPU in 7.243 seconds (100% CPU, 812897 Lips)
Vs = [1, 2, 6, 4, 7, 8, 3, 5, 9] .

正确性

现在让我们使用其他发布的配方测试此结果。通过接受的答案,我们得到:

?- mathmaze([1, 2, 6, 4, 7, 8, 3, 5, 9]).
false.

那么,它是:这是一个解决方案吗?

根据什么小浮点数可以帮助我们,可能是一个解决方案:

?- X is 1+13*2/6+4+12*7-8-11+3*(5/9)-10.
X = 66.0.

当然,在这种情况下,浮点数的帮助非常有限,因此我们使用有理数代替:

?- X is  1+13*(2 rdiv 6) +4+12*7-8-11+3*(5 rdiv 9)-10.
X = 66.

,这是一个解决方案!但是,由于接受的答案使用浮点数,因此无法识别,因为:

?- 66 is 66.0.
false.

没错! 66.0 not 66.欢迎使用20世纪40年代的开创性技术。

由于使用了浮点数,总的来说,接受的答案错过了136个解决方案。但是,由于确实找到了一些解决方案(总共6个),因此很容易忽视这些错误。为了安全起见,我建议您在推理Prolog中的数字时总是使用整数,有理数或类似的安全表示。

相关问题