我必须尝试使用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.
答案 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).
这说:
这可以使用CLPFD编写,但它不提供任何非整数除法,因此它将生成错误的答案,对于如此严格定义的问题,用all_distinct/1和{{替换排列3}}似乎不值得努力(但CLPFD对于这种问题通常是一个有用的库)。
答案 1 :(得分:1)
首先,一般说明:在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中的数字时总是使用整数,有理数或类似的安全表示。