SWI-Prolog删除具有配对出现的项目

时间:2017-04-24 06:36:08

标签: prolog

我需要一个解决方案来删除列表中包含多个匹配项的元素。 我在haskell做过,但我没有任何想法如何在Prolog中解释它 例如[1,2,2,2,4,4,5,6,6,6,6] - > [1,2,2,2,5]

Haskell中的代码:

import Data.List

count e list = length $ filter (==e) list
isnotEven = (== 1) . (`mod` 2)

removeUnique :: [Int] -> [Int]
removeUnique list = filter (\x ->  isnotEven (count x list)  ) list

2 个答案:

答案 0 :(得分:3)

以下是您的Haskell代码。

SICStus | SWI需要library(reif)

:- use_module(reif).

oddcount_t(List, E, T) :-       % reified: last argument is truth value
   tfilter(=(E), List, Eqs),
   length(Eqs, Nr),
   M is Nr mod 2,
   =(M, 1, T).

removeevenocc(List, RList) :-
   tfilter(oddcount_t(List), List, RList).

?- removeevenocc([1,2,2,2,4,4,5,6,6,6,6], R).
R = [1,2,2,2,5].

?- removeevenocc([1,X], R).
   X = 1,
   R = []
;  R = [1, X],
   dif(X, 1).

请注意最后一个问题。这里没有完全给出列表:第二个元素未知。因此,Prolog为X所有可能的值生成答案! X为1,结果列表为空,或X不为1,则列表保持不变。

答案 1 :(得分:0)

此代码段使用了一些可用的库(聚合,列表,yall),以及一些内置函数,如setof / 3和(=:=)/ 2:

?- L=[1,2,2,2,4,4,5,6,6,6,6],
|    setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds), 
|    foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = [1, 2, 2, 2, 4, 4, 5, 6, 6|...],
Ds = [4, 6],
R = [1, 2, 2, 2, 5].

修改

考虑setof / 3行为(我的错误:如果没有解决方案,setof / 3会失败),可能的更正:

?- L=[1],
(setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds);Ds=[]),
foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = R, R = [1],
Ds = [].

现在还有一个选择点,正确的语法可能是

?- L=[1],
(setof(K,C^(aggregate(count,member(K,L),C),0=:=C mod 2),Ds)->true;Ds=[]),
foldl([E,X,Y]>>delete(X,E,Y),Ds,L,R).
L = R, R = [1],
Ds = [].