谓词返回true,而不是某些值

时间:2019-06-19 18:52:50

标签: prolog

我正在尝试制作一个包含两个数字K的谓词,Num(使用谓词时为0,每次递归后都会更改),一个包含数字从1到K的列表,以及一个所有键从1到K的关联树K的值为0。在列表中找到从1到K的所有数字(Num直到此为止都找到数字)时,它返回列表NL的其余部分和一个关联树,其中每个键的值是每个数字乘以找到了。应该这样使用:

first(3, 0, [1,3,1,3,1,3,3,2,2,1], T, NL, NT)

其中T是上述树。

这是我的代码:

first(K, K, L, T, L, T):- !.
first(_, _, [], _, [], NT) :-
    empty_assoc(NT), !.
first(K, Num, [H|L], T, NL, NT) :-
    get_assoc(H, T, V),
    Newv is V+1,
    put_assoc(H, T, Newv, TT),
    V=:=0 -> Newnum is Num+1; Newnum is Num,
    first(K, Newnum, L, TT, NL, NT).

我的问题是它返回true而不是NL和NT的值。

1 个答案:

答案 0 :(得分:1)

这里的主要问题是运算符优先级。如果我们要求解释器生成listing.,则会得到:

first(A, A, B, C, B, C) :- !.
first(_, _, [], _, [], A) :-
    empty_assoc(A), !.
first(G, E, [A|H], B, I, J) :-
    (   get_assoc(A, B, C),
        D is C+1,
        put_assoc(A, B, D, _),
        C=:=0
    ->  F is E+1
    ;   F is E,
        first(G, F, H, _, I, J)
    ).

这可以使我们了解到,只有在C =:= 0不成立的情况下,我们才会对first/6进行递归调用。这可能不是您的意图。由于我们仅在条件不成立的情况下进行递归调用,因此TT

如果我们使用方括号,例如:

first(K, K, L, T, L, T):- !.
first(_, _, [], _, [], NT) :-
    empty_assoc(NT), !.
first(K, Num, [H|L], T, NL, NT) :-
    get_assoc(H, T, V),
    Newv is V+1,
    put_assoc(H, T, Newv, TT),
    (V=:=0 -> Newnum is Num+1; Newnum is Num),
    first(K, Newnum, L, TT, NL, NT).

在修复了该错误之后,我们得到一个错误:

?- first(3, 0, [1,3,1,3,1,3,3,2,2,1], T, NL, NT)
|    .
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [13] throw(error(instantiation_error,_7048))
ERROR:    [9] assoc:get_assoc(1,_7080,_7082) at /usr/lib/swi-prolog/library/assoc.pl:178
ERROR:    [8] first(3,0,[1,3|...],_7112,_7114,_7116) at /tmptest.pl:5
ERROR:    [7] <user>

这意味着我们的目标是调用get_assoc/3,但要使用非构造的关联数组。请注意,empty_assoc/1不是构造的,它仅在列表用尽时才构造。

我认为这里的核心问题是您一次做太多事情。我们可以做一些小的谓词,每个谓词只能做有限的工作。

例如,我们可以生成一个关联数组,该数组将1K之间的所有值映射为0

gen_assoc(K, A) :-
    empty_assoc(E),
    gen_assoc(K, E, A).

gen_assoc(0, A, A).
gen_assoc(K, A, C) :-
    K > 0,
    put_assoc(K, A, 0, B),
    K1 is K-1,
    gen_assoc(K1, B, C).

因此,gen_assoc(3, A)将通过一个关联数组统一A,该数组将13(包括两端)的所有数字映射到0。 >

我把剩下的作为练习。