Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 用于查找具有某些条件的元素的不完美Prolog代码_List_Prolog_Clpfd_Meta Predicate - Fatal编程技术网

List 用于查找具有某些条件的元素的不完美Prolog代码

List 用于查找具有某些条件的元素的不完美Prolog代码,list,prolog,clpfd,meta-predicate,List,Prolog,Clpfd,Meta Predicate,第一段代码: count(X, [], 0). count(X, [X|T], N) :- count(X, T, N1), N is N1 + 1. count(X, [Y|T], N) :- X \= Y, count(X, T, N). found(0, [], X). found(N, [H|T], R):- count(R, [R|T], C), C == N. found(N, [H|T], R):- count(R, [R|T], C), C \=

第一段代码:

count(X, [], 0).
count(X, [X|T], N) :-
  count(X, T, N1),
  N is N1 + 1.
count(X, [Y|T], N) :-
  X \= Y,
  count(X, T, N).
found(0, [], X).
found(N, [H|T], R):-
  count(R, [R|T], C),
  C == N.
found(N, [H|T], R):-
  count(R, [R|T], C),
  C \= N,
found(N, T, R).
它显示列表中给定元素的重复时间。(没有问题!)例如

?- count(5, [1,5,5,3,3,3,4,2], X).
X = 2.
?- found(2, [1,5,5,3,3,3,4], X).
X = 5. 
第二段代码:

count(X, [], 0).
count(X, [X|T], N) :-
  count(X, T, N1),
  N is N1 + 1.
count(X, [Y|T], N) :-
  X \= Y,
  count(X, T, N).
found(0, [], X).
found(N, [H|T], R):-
  count(R, [R|T], C),
  C == N.
found(N, [H|T], R):-
  count(R, [R|T], C),
  C \= N,
found(N, T, R).
它通过列表中给定的重复时间来显示元素。(但它并不完美)。比如说,

?- count(5, [1,5,5,3,3,3,4,2], X).
X = 2.
?- found(2, [1,5,5,3,3,3,4], X).
X = 5. 
这没关系。但是,

?- found(3, [1,5,5,3,3,3,4], X).
X = 5.

这是错误的!我不知道如何修复它。

你说计数/3没有问题,但我不同意:

?- count(X, [1,5,5,3,3,3,4,2], Z).
X = Z, Z = 1 ;
false.
我想在这里看到的是:

X = Z, Z = 1 ;
X = 5, Z = 2 ;
X = Z, Z = 3 ;
X = 4, Z = 1 ;
X = 2, Z = 1 ;
false.
在我看来,
count/3
应该能够列出除第一个之外的列表项。事实上,它之所以能够提出这一点,是因为第二条规则对榜首有所说明。您的单例警告出现是因为第一条规则,最好是这样说:

count(_, [], 0).
你用这个规则真正要说的是,“无论你在寻找什么,如果列表是空的,那么这个东西的计数是0。”我可以想出其他方法来重述这个为第一个参数生成的谓词,但是没有一个能保留这个非常令人愉快的属性。我怀疑@false会在某个时候慢慢地告诉我们为什么我们都错了。但我倾向于这样说
count/3

count(Item, List, 0) :- \+ memberchk(Item, List).
count(Item, List, N) :-
    % get us each unique item, one by one (or confirm that X is in the list)
    sort(List, Sorted), member(Item, Sorted),

    % make a list of the items that match
    bagof(Item, member(Item, List), Occurrences),

    % count them
    length(Occurrences, N).
这很奇怪也很尴尬,可能有更好的方法,但它满足了我们的两个要求:

?- count(X, [1,5,5,3,3,3,4,2], Z).
X = Z, Z = 1 ;
X = 2,
Z = 1 ;
X = Z, Z = 3 ;
X = 4,
Z = 1 ;
X = 5,
Z = 2.

?- count(0, [1,5,5,3,3,3,4,2], Z).
Z = 0 ;
false.

?- count(5, [1,5,5,3,3,3,4,2], Z).
Z = 2.
现在让我们关注
found/3
。首先,让我们更改代码以解决单例错误,这样我们就可以看到问题所在:

found(0, [], _).
found(N, [_|T], R):-
  count(R, [R|T], C),
  C == N.
found(N, [_|T], R):-
  count(R, [R|T], C),
  C \= N,
  found(N, T, R).
我们立刻看到,在第二条和第三条规则中,我们在列表的前面暗示了一个R。可能在这两种情况下,我们都想保留H并传递它,或者做一些棘手的事情。事实上,只使用L可能更安全,因为我们不必对列表做任何花哨的事情,
count/3
过程应该足够了。经检查,我不知道你想用第三条规则实现什么。事实上,我们可以将其全部删除,并得出以下定义:

found(0, [], _).
found(N, L, R):-
  count(R, L, C),
  C == N.
found(X, Y, Z) :- count(Z, Y, X).
它适用于你的两个用例,但是你猜怎么着?我们根本不需要
found/3
,因为
count/3
现在就可以了

?- count(X, [1,5,5,3,3,3,4], 3).
X = 3 ;
false.

?- count(X, [1,5,5,3,3,3,4], 2).
X = 5.
这些都是字面上的问题,比如“发生2次的元素是什么?”Prolog消除了对整个其他谓词的需要。现在,您可以用以下简单的定义对其进行简单的定义:

found(0, [], _).
found(N, L, R):-
  count(R, L, C),
  C == N.
found(X, Y, Z) :- count(Z, Y, X).

一个临别赠言:如果使用真实的、非单字母的变量名,您可能会发现自己的代码更容易调试。看看我对计数/3的定义。它稍微大一点,但更容易跟随。我经常在我自己的代码中使用
[H | T]
[X | Xs]
,但一般来说,X、Y、Z等的大量增加使得阅读代码时很难跟上,在声明性语言中,阅读代码是非常重要的,因为在声明性语言中,大多数流程实际上是关于在何处使用哪些变量。

首先要做的事情
code>count/3和
found/3
相同的

我们定义
count/3
使用并具体化术语等式:

问:“在
[a,e,e,c,c,c,d,b]
中出现
e
的次数是多少?”

问:“哪个
X
[a,e,e,c,c,c,d,b]
中正好出现三次?”

问:“哪个
X
[a,e,e,c,c,c,d,b]
中只出现一次?”


您有很多单例变量警告。我敢打赌,如果你用
\uu
替换它们,你会注意到一些问题——例如,
H
found/3
的第二条和第三条规则中发生了什么? ?- count(X,[a,e,e,c,c,c,d,b],0). dif(X,a), dif(X,b), dif(X,c), dif(X,d), dif(X,e).