prolog中列表L中X的出现次数

时间:2014-11-13 18:39:39

标签: prolog

我试图在列表L中找到X的出现次数 例如: -

occurrences(a, [b, a, b, c, a, d, a], N ).
N =3

我的代码无效。这是我的代码。

occ(K,L,N) :-  N1=0,  occ1(K,L,N1,N).

occ1(K,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
   L=[X|L1], 
   ( K=X -> N1 is N1+1, occ1(K,L1,N1,N) ; occ1(K,L1,N1,N) ).

有人能告诉我代码中有什么问题。

2 个答案:

答案 0 :(得分:2)

虽然@Kay给出的答案在修复错误方面是现实的,但它完全绕过了一个更大的问题:occ1/4的代码逻辑上不纯

这对你来说可能不是很重要, 但使用不纯的代码有几个负面后果:

  1. 不能以声明方式读取不纯的代码,只能在程序上读取。
  2. 调试不纯的代码往往是乏味且痛苦的。
  3. 不纯的谓词与纯粹的谓词不太“关系”。
  4. 逻辑杂质阻碍了代码的重复使用。
  5. 因为它不是单调的,所以不纯的代码很容易导致逻辑上不合理的答案,特别是在使用非基础术语时。
  6. 为了表明在按照建议@Kay“修复”后代码中存在这些问题,让我们考虑“已更正”的代码和一些查询。首先,这是更正后的代码:

    occ(K,L,N) :-  N1=0,  occ1(K,L,N1,N).
    
    occ1(_,[],N1,N) :- N=N1.
    occ1(K,L,N1,N) :-
       L=[X|L1], 
       ( K=X -> N2 is N1+1, occ1(K,L1,N2,N) ; occ1(K,L1,N1,N) ).
    

    以下是您在问题中提供的查询:

    ?- occ(a,[b,a,b,c,a,d,a],N).
    N = 3 ;
    false.
    

    好!如果我们以不同的方式编写查询怎么办?

    ?- A=a,B=b,C=c,D=d, occ(a,[B,A,B,C,A,D,A],N).
    A = a, B = b, C = c, D = d, N = 3 ;
    false.
    

    好!如果我们重新排序目标怎么办?逻辑连接应该是可交换的......

    ?- occ(a,[B,A,B,C,A,D,A],N), A=a,B=b,C=c,D=d.
    false.
    

    失败! 似乎 occ1/4没问题,但现在我们得到了一个逻辑上不健全的答案。

    使用逻辑纯代码可以避免这种情况: 查看我在my answer中向相关问题“Prolog - count repititions in list (sic)”提供的纯色和单调代码。

答案 1 :(得分:1)

问题是

N1 is N1+1

变量不能被覆盖"在Prolog。您只需要一个新变量,例如

N2 is N1+1, occ1(K,L1,N2,N)

问题"我们可以替换特定的列表元素吗?如果是,语法是什么?":

您只能构建新列表:

replace(_, _, [], []).
replace(Old, New, [H0|T0], [H1|T1]) :-
    (H0 = Old -> H1 = New; H1 = H0),
    replace(Old, New, T0, T1).