2015-11-09 31 views
0

我有一个列表分割清单上的条件

[a,a,a,a,b,b] 

我的目标是将其分割成

[[a,a,a,a],[b,b]] 

谓语到目前为止

split1([],[]). 
split1([A1|T],[[H1,H2]|B]):- 
A1=[H1,H2], 
H1=H2, 
split(T,B). 

split1([],[]). 
split1([A1|T],[[H1,H2]|B]):- 
A1=[H1,H2], 
H1\=H2, 
split(T,B). 

对不起,我已经实现为noob问题学习序言。

+1

什么,当你试图评估你的断言会发生什么?你期望会发生什么?你是否试图追踪你的程序以查看它出错的地方(如果有的话)? –

+0

你对'[a,a,a,b,b,a,b,a,a]'有何期望? – repeat

+0

[[a,a,a],[b,b],[a],[b],[a,a]] –

回答

3

这可以非常类似于your other problem。这里有相关的想法。

由于您的结果有计数器,您将需要保留一个正在运行的重复元素列表。因此,考虑一个辅助谓词,其中包含当前正在运行的重复列表。这种“运行列表”通常在Prolog中使用,并被称为累加器。现在

split(L, C) :- 
    split(L, [], C). % Start repeat list accumulator at [] 

你需要考虑几个不同的情况:

split([], _, []).     % This is an easy one! 

这是说,如果我压缩空单,我得到一个空列表。

split([H], A, [[H|A]]).   % This is an easy one! 

这一个说,如果我收集一个元素的列表和我目前正在运行的重复列表A,那么结果是[[H|A]]

split([H, H|T], A, TC) :- 
    ... 

这是我有一个正在运行的重复列表,A的情况下,元素仍然重复。结果将是一个列表TC,但我不知道它看起来像什么,因为我们仍处于重复周期,它将需要通过递归确定。这个谓词应该是什么样子?在本节中将需要递归调用split1将有一个新的累加器列表。它是什么样子的?。

split([H1, H2|T], A, [[H1|A]|TC]) :- 
    dif(H1, H2), 
    ... 

这是我有一个正在运行的重复列表,A,并在H1重复停止的情况。由于当前周期的重复与H1结束,我们知道结果看起来像[[H1|A]|TC]因为重复周期与H1完成,整个重复列表H1与尾部A(这只是预先考虑到H1A,和他们都相同的元素)。我们还没有通过递归来确定列表TC的其余部分。这个谓词实现应该是什么样的?

还有其他方法可以完成上述逻辑(例如,使用->;结构等),但这样做会使它变得简单。

尝试将这些看作是规则,其中谓词子句的头部是断言,如果子句的以下元素为真,断言将为真。并递归思考。


作为一种事后,这可以无需单独的蓄电池使用结果进行累加器完成:

split([], []). 
split([H], [[H]]). 
split([H1,H2|T], [[H1]|R]) :- 
    dif(H1, H2), 
    split(...).     % left as an exercise 
split([H,H|T], [[H|TH]|R]) :- 
    split(...).     % left as an exercise 
+1

s(X):“... ,但这会保持简单。“不只是简单,但*正确*。 – repeat

+0

......你知道,这个“dif/2”将永远留下一个选择点。 – false

1

你应该看看SWI-Prolog implementation of group_pairs_by_key/2。它比你需要的多一点,但我想很容易省去不必要的部分。

用,因为它是目前谓词,你可以这样做:

?- L = [a,a,b,b,a,b,b], 
    keys_values_pairs(L, L, P), 
    group_pairs_by_key(P, G), 
    keys_values_pairs(_, Result, G). 
L = [a, a, b, b, a, b, b], 
P = [a-a, a-a, b-b, b-b, a-a, b-b, b-b], 
G = [a-[a, a], b-[b, b], a-[a], b-[b, b]], 
Result = [[a, a], [b, b], [a], [b, b]]. 

所以你只需要弄清楚如何让出来让不需要的一谓语键和值,但只有一个值。由于这显然是功课,因为你甚至没有在答案中付出足够的努力,所以我将把它作为一个练习。

2

所有你需要的是splitlistIfAdj/3 and dif/3。示例使用:

?- splitlistIfAdj(dif, [a,a,a,b,b,c,a,a,a,a], Xss). 
Xss = [[a,a,a],[b,b],[c],[a,a,a,a]]. 
+4

如果只有一个不需要另外定义'splitlistIfAdj/3','dif/3'和'if_/3' ....那么camelCase是怎么回事? –

+3

关于骆驼......一个坏习惯,我知道。 – repeat

+0

我并不太在意额外的定义。我们也都使用其他库谓词,即使它们的实现经常很脆弱。 – repeat

1

一个简单的定义:

groups([X|Xs],[G|Gs]) :- take(X,Xs,G,Rs), groups(Rs, Gs). 
groups([],[]). 

take(X,[X|R],[X|G],S) :- !, take(X,R,G,S). 
take(X,R,[X],R). 

采取/ 4消耗并存储匹配的元素,留下其余部分组

+0

@repeat:这怎么会发生?统一123名单? – CapelliC

+0

我的不好!我重新做了测试,它工作。我错误地将你的代码粘贴到Prolog解释器中...对于模糊的问题抱歉。 – repeat

+1

@repeat:谢谢。请原谅我的答案的天真性,它对初学者的意义,我认为在挖掘高级问题之前需要掌握Prolog的基础知识 – CapelliC