用(少数)自然语言

时间:2015-06-10 18:51:29

标签: prolog

假设一个列表,每个元素可以是:

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完全未定义。

1 个答案:

答案 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.