prolog中的拆分列表基于条件

时间:2015-11-09 09:44:47

标签: list prolog prolog-dif

我有一个清单

[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问题学习prolog感到抱歉。

4 个答案:

答案 0 :(得分: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 :(得分: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]].

答案 2 :(得分: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]].

所以你只需要弄清楚要留下什么来获得一个谓词,它不需要一个键和一个值的,而只需要一个值。由于这显然是家庭作业,因为你甚至没有在答案中付出足够的努力,我将把它留作练习。

答案 3 :(得分: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消耗并存储匹配元素,剩余部分留给组