3

消除列表元素的连续重复。

我的解决方案是:

compress([X,X|Xs], Q) :-
   compress([X|Xs], Q).
compress([X,Y|Xs], Q) :-
   X \= Y,
   compress([Y|Xs], QR),
   append([X], QR, Q).
compress([X|[]], Q) :-
   compress([], QR),
   append([X], QR, Q).
compress([], []).

而且,由于我是初学者而且我没有逻辑范式的经验,所以我请你说出我可以改进的地方以及为什么我的解决方案不能做到最好。

例如,X \= Y在我看来并不漂亮。

4

2 回答 2

5

我们从谓词的名称开始。

为什么要用祈使句来表示关系?一个好的 Prolog 程序可以在所有方向上使用,而命令式总是建议一个特定的方向或使用方式。因此,选择一个声明性名称并以通用性和为目标。

接下来,最一般的查询呢:

?- compress(Ls, Cs).
ERROR: Out of local stack

不大好!我们希望这至少会产生一些答案。

如果我们使用迭代深化会怎样:

?- 长度(Ls,_),压缩(Ls,Cs)。
Ls = Cs, Cs = [] ;
Ls = Cs,Cs = [_G841];
Ls = [_G841, _G841],
Cs = [_G841] ;
Ls = [_G841, _G841, _G841],
Cs = [_G841] 。

嗯!很多答案都不见了!元素不同的情况呢?正如您已经直观地期望的那样,正是使用不纯谓词导致了这种效果。

因此,使用,即 ,dif/2来表示两个术语是不同的。它可以在各个方向使用!

此外,DCG ( ) 在描述列表时通常很有用。

所以,总的来说,这个怎么样:

压缩([])-> []。
压缩([L|Ls])-> [L],compression_(Ls,L)。

压缩_([],_)-> []。
压缩_([X|Xs], L) -->
        ( { X = L },
            压缩_(Xs,L)
        ; { 差异(X,L)},
            [X],
            压缩_(Xs,X)
        )。

我们使用接口谓词phrase/2来处理 DCG。

使用示例:

?- 短语(压缩(Ls),Cs)。
Ls = Cs, Cs = [] ;
Ls = Cs,Cs = [_G815];
Ls = [_G815, _G815],
Cs = [_G815] 。

?- 长度(Ls,_),短语(压缩(Ls),Cs)。
Ls = Cs, Cs = [] ;
Ls = Cs,Cs = [_G865];
Ls = [_G865, _G865],
Cs = [_G865] ;
Ls = Cs, Cs = [_G1111, _G1114],
差异(_G1114,_G1111)。

从这里拿走!提高确定性,找到更好的名称等。

于 2016-05-22T15:38:48.797 回答
4

基于@mat (+1) 的答案,为什么不提高这种情况的确定性:

?- 短语(压缩([a,a,b,b,b,c,c,c,c,d]),Xs)。
Xs = [a, b, c, d] ;
假的。

SWI 表明目标没有确定地成功; false

我们可以compression_//2通过使用if_//3—— 的 dcg类似物来if_/3

压缩_([],_)-> []。
压缩_([X|Xs], L) -->
   if_ (X = L, % 这一项是否等于前一项?
       compression_(Xs, L), % yes: 旧的“运行”继续
       ([X],压缩_(Xs,X)))。% no: 新的“运行”开始

示例查询:

?- phrase(compression([a,a,b,b,b,c,c,c,c,d]), Xs).
Xs = [a, b, c, d].                            % succeeds deterministically
于 2016-05-22T17:29:10.757 回答