我是Prolog的新手,正在尝试做这个问题。我们有一个列表
List = [a,a,a,a,b,c,c,a,a,d,e,e,e,e]
我想将其打包到相似元素的子列表中。
Pack( [a,a,a,a,b,c,c,a,a,d,e,e,e,e], Sublists)
应提供
Sublists = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]
这是我到目前为止尝试过的:
pack([],[],[]).
pack([H],[H],[H]).
pack([H,H1|T],Z,X):- H==H1 , append([H],Z,Z1) , pack([H1|T],Z1,X).
pack([H,H1|T],Z,X):- H=\=H1 , append([H],Z,Z1) ,
append(Z1,X,Xs) , pack([H1|T],Z1,Xs).
以下是错误:
Arithmetic: `a/0' is not a function In: [4] a=\=b [3] pack([a,b|...],[a,a],_1608) at line 13 [2] pack([a,a|...],[a],_1688) at line 13 [1] pack([a,a|...],[],_1762) at line 13
先谢谢了。我正在尝试解决这些问题:
答案 0 :(得分:3)
您可以通过简单的列表处理并使用SWI Prolog的dif/2
来解决此类问题,以提供常规解决方案:
pack([], []). % packing empty is empty
pack([X], [[X]]). % packing a single element
pack([X,X|T], [[X|PH]|PT]):- % rule for packing when next two terms are the same
pack([X|T], [PH|PT]).
pack([X,Y|T], [[X]|PT]):- % rule for different term
dif(X, Y),
pack([Y|T], PT).
2 ?- pack([a,a,a,a,b,c,c,a,a,d,e,e], L).
L = [[a, a, a, a], [b], [c, c], [a, a], [d], [e, e]] ;
false.
3 ?- pack(L, [[a,a,a], [b,b], [c]]).
L = [a, a, a, b, b, c] ;
false.
4 ?-
答案 1 :(得分:2)
请注意,lurker's solution仍然存在一些性能问题。请参阅; false
了解每种解决方案?这表明Prolog仍然保留一些内存(称为选择点-实际上可能甚至有几个这样的选择点)。但是,在许多情况下,不需要这样的选择点。这是一个解决该问题的解决方案(在Haskell的上下文中,名称group
代替pack
很常见)
group([], []).
group([E|Es], [[E|Gs]|Gss]) :-
igroup(Es, E, Gs, Gss).
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
( E\=F
-> Gs1=[], Gss1=[[E|Gs2]|Gss2]
; E==F
-> Gs1=[E|Gs2], Gss1=Gss2
; E=F,
Gs1=[E|Gs2], Gss1=Gss2
; dif(E, F),
Gs1=[], Gss1=[[E|Gs2]|Gss2]
),
igroup(Es, E, Gs2, Gss2).
请注意,如何将E
和F
的相等性测试分为四种情况:
第一个E \= F
意味着两者绝对不同。
然后是E == F
,这意味着两者绝对相同。
然后是E = F
,这是等式的一般情况,
dif(E, F)
,这是一般不平等的情况
在后两种情况下,没有->
,因为两者都可能是正确的。
由于维护这么多案件非常麻烦,因此有library(reif)
对于
SICStus和
SWI可以使内容更紧凑:
igroup([], _, [], []).
igroup([E|Es], F, Gs1, Gss1) :-
if_(E = F
, ( Gs1 = [E|Gs2], Gss1 = Gss2 )
, ( Gs1 = [], Gss1 = [[E|Gs2]| Gss2] )),
igroup(Es, E, Gs2, Gss2).
答案 2 :(得分:1)
您得到的错误是因为如果=\=/2
的 number 不等于expr1
,则expr2
为真。相反,您可以使用\=\2
来评估\+term1=term2
。 ==/2
的值为term1 equivalent to term2
,如果=:=/
是 number 等于{{1 }}。我在您的代码中发现的另一个错误是您没有清除中间列表。将类似元素列表添加到expr1
列表后,必须刷新其中的值。我已使用剪切expr2
来减少回溯。相反,如果编写互斥谓词,那就更好了。
我已经编辑了您的代码:
Sublists
输出:
!
希望这会有所帮助。