假设一个列表,每个元素可以是:
a)数字1,2,...... 9
b)数字10,100,10000,...(形式为10 ^(2 ^ n)的数字,其中n> = 0)。
需要一个(尽可能简单)规则,将此列表计算为一个整数。此评估的示例如下:
[1] => 1
[2] => 2
[10 1] => 11
[2 10 1] => 21
[2 100 1 10 4] => 214
[2 10 1 100 4] => 2104
[2 10 1 100 10000] => 21000000
换句话说,数字10,100,......相当于十分之一,数百,百万......,用英语和评估规则是英语和其他语言中常见的:10,100和#34 ;乘法"它们之前的值,它们之后的数字被添加。
(我知道这个定义不是一个确切的定义,但找到一个好的定义是问题的一部分。如果有必要,请不要犹豫要求更多的例子。)
请注意,与自然语言相同,数字零不是必需的。甚至像初始语言一样,语法中也没有。
附录
这个问题的主要困难是[2 10000 3 10]这样的表达式不能被视为(2 * 10000 + 3)* 10,而是2 * 10000 + 3 * 10。另一个例子是[2 10 1 10000 3 10],即(2 * 10 + 1)* 10000 + 3 * 10.
不作业的证明:对这种编号(以及一般来说,自然语言)的兴趣是,在某些情况下,它们比二进制更安全。例如,在超市价格的背景下,"两千个等等#34;保持一定的意义,而1001blah完全未定义。
答案 0 :(得分:3)
凭借独创性,我会开始涵盖模式......
test :- forall(member(L=R, [
[1] = 1,
[2] = 2,
[10, 1] = 11,
[2, 10, 1] = 21,
[2, 100, 1, 10, 4] = 214,
[2, 10, 1, 100, 4] = 2104,
[2, 10, 1, 100, 10000] = 21000000
]), test(L, R)).
test(L, R) :-
pattern(L, E), R =:= E -> writeln(ok(L,R)) ; writeln(ko(L,R)).
pattern([A], A) :- dig(A).
pattern([A, B], A+B) :- ten(A), dig(B).
pattern([A, B, C], A*B+C) :- mul_ten(A, B), dig(C).
pattern([A, B, C, D, E], A*B + C*D + E) :- mul_ten(A,B), mul_ten(C,D), B > D, dig(E).
pattern([A, B, C, D, E], ((A*B+C)*D)+E) :- mul_ten(A,B), ten(D), dig(E). % doubt...
pattern([A, B, C, D, E], (A*B+C)*D*E) :- mul_ten(A,B), ten(D), ten(E). % doubt...
dig(D) :- between(1,9,D).
ten(T) :- between(0,10,E), T =:= 10^(2^E). % 10 -> inappropriate (too much zeroes ?)
mul_ten(M,T) :- between(1,9,M), ten(T). % 9 -> inappropriate ?
普通模式匹配。运行:
?- test.
ok([1],1)
ok([2],2)
ok([10,1],11)
ok([2,10,1],21)
ok([2,100,1,10,4],214)
ok([2,10,1,100,4],2104)
ok([2,10,1,100,10000],21000000)
true.
我认为递归的空间很小,afaik成语涵盖经常使用的案例,但没有' smart'评价......无论如何,我无法真正找到自己的方式(也就是说,我永远不会使用)这种模式
[2 10 1 100 4] => 2104
现在使用DCG和CLP(FD)编辑:
:- use_module(library(clpfd)).
test :- forall(member(L=R, [
[1] = 1,
[2] = 2,
[10, 1] = 11,
[2, 10, 1] = 21,
[2, 100, 1, 10, 4] = 214,
[2, 10, 1, 100, 4] = 2104,
[2, 10, 1, 100, 10000] = 21000000
]), test(L, R)).
test(L, R) :-
phrase(pattern(E), L), R #= E -> writeln(ok(L,R)) ; writeln(ko(L,R)).
pattern(A) --> dig(A).
pattern(A+B) --> ten(A), dig(B).
pattern(A*B+C) --> mul_ten(A, B), dig(C).
pattern(A*B+C*D) --> mul_ten(A, B), mul_ten(C, D).
pattern(A*B + C*D + E) --> mul_ten(A,B), mul_ten(C,D), dig(E).
pattern(((A*B+C)*D)+E) --> mul_ten(A,B), [C], ten(D), dig(E). % doubt...
pattern((A*B+C)*D*E) --> mul_ten(A,B), [C], ten(D), ten(E). % doubt...
dig(D) --> [D], {D #>= 1, D #=< 9}.
ten(T) --> [T], {T #>= 1, T #= (10^(2^E)), E #> 0, E #=< 10}.
mul_ten(M,T) --> dig(M), ten(T).
编辑我喜欢op / 3指令,也是......
:- op(100,fx, dig).
:- op(100,fx, ten).
:- op(100,xfx, mul).
pattern(A) --> dig A.
pattern(A+B) --> ten A, dig B.
pattern(A*B+C) --> A mul B, dig(C).
pattern(A*B+C*D) --> A mul B, C mul D.
pattern(A*B+C*D+E) --> A mul B, C mul D, dig E.
pattern(((A*B+C)*D)+E) --> A mul B, [C], ten D, dig E. % doubt...
pattern((A*B+C)*D*E) --> A mul B, [C], ten D, ten E. % doubt...
dig D --> [D], {D #>= 1, D #=< 9}.
ten T --> [T], {T #>= 1, T #= (10^(2^E)), E #> 0, E #=< 10}.
M mul T --> dig M, ten T.