List 检查是否有任何元素';s的频率高于一个极限
我想解决一个问题,我有一个Prolog元素列表。如果任何元素频率大于List 检查是否有任何元素';s的频率高于一个极限,list,prolog,prolog-dif,clpfd,List,Prolog,Prolog Dif,Clpfd,我想解决一个问题,我有一个Prolog元素列表。如果任何元素频率大于N,则返回false。我的期望如下 ?- frequency([1,2,2,2,5],3). true. ?- frequency([1,2,2,2,2,5],3). false. 我有一个获取特定元素频率的代码。对这个问题有什么想法吗 count(_, [], 0) :- !. count(X, [X|T], N) :- count(X, T, N2), N is N2 + 1. count(X, [Y|
N
,则返回false。我的期望如下
?- frequency([1,2,2,2,5],3).
true.
?- frequency([1,2,2,2,2,5],3).
false.
我有一个获取特定元素频率的代码。对这个问题有什么想法吗
count(_, [], 0) :-
!.
count(X, [X|T], N) :-
count(X, T, N2),
N is N2 + 1.
count(X, [Y|T], N) :-
X \= Y,
count(X, T, N).
您可以首先尝试思考解决此类问题的最“便宜”(就写作而言)的方法。我通常会想办法用标准的命令行工具来完成它。例如,要查找名为
foo
的文本文件中所有行的出现情况,可以编写(在Bash中):
您可以阅读手册,但以下是一个运行示例:
$ cat foo
a
b
b
b
c
d
d
a
b
d
c
$ sort foo | uniq --count
2 a
4 b
2 c
3 d
现在,一种询问“是否有任何一行的计数超过3?”的方法是使用awk
如下:
sort foo | uniq --count | awk '{ if ($1 > 3) exit(1) }'
foo | bar | baz # etc
foo(In, X0), bar(X0, X1), baz(X1, X2) % etc
frequency(Es, M) :-
list_counts(Es, Xss),
maplist(arg(2), Xss, Zs),
maplist(#>=(M), Zs).
(我相信还有更聪明的方法。)
使用上述文件,您可以获得:
$ sort foo | uniq --count | awk '{ if ($1 > 3) exit(1) }'
$ echo $?
1
$ sort foo | uniq --count | awk '{ if ($1 > 4) exit(1) }'
$ echo $?
0
好的,那这对你学习Prolog有什么帮助呢?好的,一种模拟管道的简单方法如下:
sort foo | uniq --count | awk '{ if ($1 > 3) exit(1) }'
foo | bar | baz # etc
foo(In, X0), bar(X0, X1), baz(X1, X2) % etc
frequency(Es, M) :-
list_counts(Es, Xss),
maplist(arg(2), Xss, Zs),
maplist(#>=(M), Zs).
在序言中写一个连词,如下所示:
sort foo | uniq --count | awk '{ if ($1 > 3) exit(1) }'
foo | bar | baz # etc
foo(In, X0), bar(X0, X1), baz(X1, X2) % etc
frequency(Es, M) :-
list_counts(Es, Xss),
maplist(arg(2), Xss, Zs),
maplist(#>=(M), Zs).
回到您的问题:您可以使用msort/2
(或者在您使用的实现中调用稳定排序谓词)。然后,您需要计算相同元素的运行次数。在SWI Prolog中,至少您有。例如,您可以使用它,如下所示(与同一库中的其他谓词一起,您可以在同一链接中看到代码):
在这一点上,您已经对中每个元素的出现次数进行了排序Counts
(无可否认,这比uniq--count
更详细),您只需检查其中是否有任何元素超出了您的限制。要执行与上面在Prolog中的awk
调用非常类似的操作:
maplist(=<(3), Counts)
maplist(这段代码是怎么回事
frequency(L,N):-getall(L,L1), max_member(A,L1),A=<N.
getall([],[]).
getall(L,N):-append([],[X1|T],L),count(X1,L,N1),getall(T,N2),append([N1],N2,N).
频率(L,N):-getall(L,L1),max_成员(A,L1),A=使用
示例查询:
?- frequency([1,2,2,2,5], 3).
true.
?- frequency([1,2,2,2,2,5], 3).
false.
多亏了这一点,我们可以提出相当一般的问题,也可以得到逻辑上合理的答案
?- frequency([A,B,C], 2).
A=B , dif(B,C)
; A=C , dif(B,C)
; dif(A,C), B=C
; dif(A,B), dif(A,C), dif(B,C).
你被困在哪里了?你有没有尝试过实现frequency/2
?蛮力方法(效率不高,但会奏效)是递归地遍历输入列表的每个元素,并对照最大值检查它在原始列表中的频率(使用count/3
谓词)。请更具体一些!什么是“频率”?应该?-频率([1,2,2,3,2,4],3)。
成功了?那么呢?-频率([1,2,2,3,2,2,4],3).
@lukercount/3
给出一个特定数字的频率。我想取最大频率,它应该小于4。如何获得它?@repect我的期望是任何大于3的频率返回false。?-频率([1,2,2,3,2,2,2,4],3)。
这里2的频率是5。而5>3。然后它将返回false.s(X):我喜欢这种方法,但我们使用的是相同的工具…最后,这一切都取决于您使用的工具。我只有SWI Prolog(版本7.1.17)“这是答案吗?”GAMSH,这是答案,你自己试过了吗?“重复你可能已经听说过这个概念。在编程语言和工具的背景下,我尝试并没有找到关于该主题的好论文,也不知道它们如何影响程序员和他们可能考虑的解决方案。我相信必须有。有点什么,我只是不知道到底要找什么。@Gamsh你的问题看起来很像家庭作业,关于如何提问和回答这些问题有很多建议。我试着遵循这些指导原则。如果这不是家庭作业,我很抱歉,但是,“给我代码”仍然不好。为什么要在某个东西后面附加一个空列表:append([],[X1 | t],L)
?取列表中的第一个元素X1
和其余的T
,因此附加一个空列表。为什么不[X1 | T]=L
?同样,为什么不附加一个元素而不是[N1 | N2]= N< /代码>?<代码>附件/ 3 < /代码>是一个有用的谓词,但是“统一”和“模式匹配”甚至更好些。“Giththan是可以的。在这种情况下,一旦找到了数字<代码> 2 /代码>并计数频率。那么尾部分也会找到。我们如何才能消除这个问题?”重复。是的,我会考虑。谢谢。很好的回答。当然是。一个很好的解决方案。