prolog查找列表的基数
我已经编写了一个Prolog代码来查找列表的基数,即不同元素的数量。它给出了正确的输出,但它运行了多次,我似乎不能让我的头围绕它。我用过调试器,但不明白出了什么问题prolog查找列表的基数,prolog,Prolog,我已经编写了一个Prolog代码来查找列表的基数,即不同元素的数量。它给出了正确的输出,但它运行了多次,我似乎不能让我的头围绕它。我用过调试器,但不明白出了什么问题 member(A, [A|_]). member(A, [_|L]) :- member(A, L). crdnlty([],0). crdnlty([A|R],N) :- ( \+ member(A, R), crdnlty(R, N1), N is N1+1 ); (
member(A, [A|_]).
member(A, [_|L]) :- member(A, L).
crdnlty([],0).
crdnlty([A|R],N) :-
(
\+ member(A, R),
crdnlty(R, N1),
N is N1+1
);
(
member(A, R),
crdnlty(R, N)
).
成员检查剩余列表中是否存在如果不存在,即该元素的最后一次出现,则基数增加1 例如,如果我运行查询
crdnlty([1,2,1,1], N).
它回来了
N = 2 ;
N = 2 ;
false.
但它应该会回来
N = 2 ;
false.
最好构建一个不同元素的列表,并为基数指定其长度:
crdnlty([A|R],N) :- distinct(R,N,[A],1).
% distinct(L,N,DL,DN): There are N distinct values in list L+DL,
% assuming there are DN distinct values in list DL alone.
distinct([],N,_,N).
distinct([A|R],N,DL,DN) :-
(
\+ member(A, DL),
DN1 is DN+1,
distinct(R, N, [A|DL], DN1)
);
(
member(A, DL),
distinct(R, N, DL, DN)
).
这不是答案,只是一个不适合评论的测试建议。 除了不需要的重复解决方案之外,还有一个关于如何测试谓词的问题。一个简单的替代解决方案是使用ISO Prolog标准谓词
sort/2
和事实上的标准谓词length/2
。替代解决办法可以是:
cardinality(List, Cardinality) :-
sort(List, Sorted),
length(Sorted, Cardinality).
我们可以使用此替代解决方案定义一个属性,您的解决方案必须遵守该属性,该属性允许快速检查您的解决方案(暂时忽略不需要的非确定性):
使用Logtalk的lgtunit
工具提供的快速检查实现(您可以在大多数Prolog系统中运行;在本例中,我将使用GNU Prolog):
当然,QuickCheck可以显示bug,但不能证明它们不存在。这就是说,Logtalk的QuickCheck实现的一个显著特征是,它在生成随机值之前尝试指定类型的琐碎/角落情况。这有助于确保随机测试不会遗漏明显的测试用例(如我们接下来所示)
如果我们测试Scott Hunter提供的解决方案,会发生什么
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
* quick check test failure (at test 1 after 0 shrinks):
* property([])
no
事实上,他的解决方案没有考虑到列表可能是空的。假设这被认为是一个bug,添加缺少的子句:
crdnlty([], 0).
重新测试:
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
% 2000 random tests passed
(1509 ms) yes
您是否尝试过逐步执行这个过程,以了解为什么它会提出两种方法来推导证明?我已经逐步执行了这个过程,并意识到在A=1和R=[]的情况下,多个规则都适合这个情况,那么Prolog是否会同时适合这两种情况并给出从这两种情况推导出的答案@Scotthunter给你投票,因为这似乎是这里的社会规范。不要投好的答案,但要投好答案中的评论。
crdnlty([], 0).
| ?- lgtunit::quick_check(property(+list(integer)), [n(2000)]).
% 2000 random tests passed
(1509 ms) yes