Prolog 序言计数频率
是否可以编写一个谓词,它接受一个输入列表并输出一个带有键值对的输出列表 例如:Prolog 序言计数频率,prolog,Prolog,是否可以编写一个谓词,它接受一个输入列表并输出一个带有键值对的输出列表 例如: freqs([a,b,a,a,b,c],L). L = [(a,3),(b,2),(c,1)] 如果可能的话,我更愿意这样做。我所知道的最远的就是这个 freqs([],[]). freqs(In,Out):- freqs(In,[],Out). freqs([],Out,Out). freqs([X|Xs],Table,Out):- \+ member((X,_),Table), fre
freqs([a,b,a,a,b,c],L).
L = [(a,3),(b,2),(c,1)]
如果可能的话,我更愿意这样做。我所知道的最远的就是这个
freqs([],[]).
freqs(In,Out):-
freqs(In,[],Out).
freqs([],Out,Out).
freqs([X|Xs],Table,Out):-
\+ member((X,_),Table),
freqs(Xs,[(X,1)|Table],Out).
freqs([X|Xs],Table,Out) :-
member((X,N),Table),
% stuck
更具体地说,如何增加N?
还有其他不需要辅助谓词的解决方案吗?您可以使用公共库谓词select/3或selectchk/3(如果也可用),而不是member/2。类似于第三条:
freqs([X|Xs],Table,Out) :-
selectchk((X,N),Table, Others),
M is N + 1,
freqs(Xs, [(X,M)| Others], Out).
但是,由于您似乎关心性能,如果将第二和第三个子句组合在一起,则速度会更快,从而生成以下完整的谓词定义:
freqs([], Out, Out).
freqs([X| Xs], Table, Out) :-
( select((X,N), Table, Others) ->
M is N + 1,
freqs(Xs, [(X,M)| Others], Out)
; freqs(Xs, [(X,1)| Table], Out)
).
这样,对于每个输入列表元素,只需在表中查找一次X,N项
电话示例:
?- freqs([a,b,a,a,b,c],L).
L = [(c, 1), (b, 2), (a, 3)].
另一种解决方案是,首先使用标准的sort/2谓词对输入列表进行排序,这通常在logn上,然后遍历生成的排序列表一次,这当然是在logn上。如此类推*logn+的复杂性。但是,正如Will Ness所解释的,如果您的输入列表很大,则可能需要查看Prolog系统库以获得良好的字典实现。您可以使用公共库谓词select/3或selectchk/3(如果还可用),而不是member/2。类似于第三条:
freqs([X|Xs],Table,Out) :-
selectchk((X,N),Table, Others),
M is N + 1,
freqs(Xs, [(X,M)| Others], Out).
但是,由于您似乎关心性能,如果将第二和第三个子句组合在一起,则速度会更快,从而生成以下完整的谓词定义:
freqs([], Out, Out).
freqs([X| Xs], Table, Out) :-
( select((X,N), Table, Others) ->
M is N + 1,
freqs(Xs, [(X,M)| Others], Out)
; freqs(Xs, [(X,1)| Table], Out)
).
这样,对于每个输入列表元素,只需在表中查找一次X,N项
电话示例:
?- freqs([a,b,a,a,b,c],L).
L = [(c, 1), (b, 2), (a, 3)].
另一种解决方案是,首先使用标准的sort/2谓词对输入列表进行排序,这通常在logn上,然后遍历生成的排序列表一次,这当然是在logn上。如此类推*logn+的复杂性。但是,正如Will Ness所解释的,如果您的输入列表很大,那么可能需要查看Prolog系统库以获得良好的字典实现。以状态传递样式编写谓词函数,在遍历列表时更新表,就像在函数式编程语言中一样,制作一个修改过的副本,而不是一个不可能的值的变异
对于线性表,它当然是2
将其保持为一个开放的二叉搜索树,树的叶子上有未设置的logvars,当遇到一个新的键时,树将被扩展,这会像往常一样将复杂性降低到logn上。你的钥匙必须是可比的。原子是
关于可扩展查找表的示例,请参见这里的列表;使其成为树也是完全可行的。以状态传递的方式编写谓词函数,在遍历列表时更新表,就像在函数式编程语言中一样,生成一个修改过的副本,而不是不可能的值变异
对于线性表,它当然是2
将其保持为一个开放的二叉搜索树,树的叶子上有未设置的logvars,当遇到一个新的键时,树将被扩展,这会像往常一样将复杂性降低到logn上。你的钥匙必须是可比的。原子是
关于可扩展查找表的示例,请参见这里的列表;把它变成一棵树也是完全可行的。你能给出一些字典实现的示例链接吗?@WillNess一个候选字典实现将是YAP、SWI Prolog、Logtalk中的红黑树实现,可能还有其他实现。它提供了一个partial_map/4元谓词,该谓词接受一个可用于更新计数器的闭包。谢谢!你能给出一些字典实现的示例链接吗?@WillNess一个候选字典实现是YAP、SWI-Prolog、Logtalk中的红黑树实现,可能还有其他实现。它提供了一个partial_map/4元谓词,该谓词接受一个可用于更新计数器的闭包。谢谢!