【问题标题】:How to merge the elements in a list in a simpler way? Prolog如何以更简单的方式合并列表中的元素?序言
【发布时间】:2021-03-18 15:46:58
【问题描述】:

我正在尝试合并列表中的元素,规则如下:

1. 合并列表的方式是,如果列表中的 2 个连续数字是相同的数字,则它们应通过求和合并为一个(即 [4,4,0,0] - > [8,0,0,0])。

2. 新合并的图块不能与另一个图块合并 在同一回合平铺(示例:[4,4,8,0] -> [8,8,0,0] True,但 [16,0,0,0] False)

3. 列表长度应为 4。如果列表在合并后减少,则在尾部添加一个零。 (例如:[4,4,0,2] -> [8,0,2,0])。

4.注意零的情况:[0,0,2,2] -> [0,4,0,0]。

我已经能够创建代码,但是我想找到一个更简单的方法来详细解释。

我的做法:

merge([H|T],L):-
   merge2([H|T],J),
    (
    length(J,2)->  
    append(J,[0,0],L);
    length(J,3)->  
    append(J,[0],L);length(J,4)-> J=L).

merge2(_,[]).
merge2([X],[X|_]).
merge2([H1,H2|T],[W|L]):-
    H1=H2,
    W is H1+H2,
    merge2(T,L).
merge2([H1,H2|T],[H1|L]):-
    H1\=H2,
    merge2([H2|T],L).

【问题讨论】:

  • 尾部的新零是从哪里来的?为什么不 [4,4,0,0] --> [8,0] 和 [4,4,8,0] ->[8,8,0]?
  • 列表的长度应该是 4,所以每当一个动作发生时,如果长度减小,则添加 0..
  • [2,2,2,2] 怎么样? -> [4,2,2,0] 还是 [4,4,0,0]?
  • @Raubsauger 它应该是 [4,4,0,0]
  • 只是为了清楚:[4,4,0,2] -> [8,0,2,0] 而不是 [8,2,0,0], [0,0, 2,2] -> [0,4,0,0] 而不是 [4,0,0,0]?

标签: list merge prolog


【解决方案1】:

长度 4 不够长,不能只写案例:

merge( [A,B,C,D], Y) :-
  ( A=B -> ( C=D -> X=[A+B,C+D,0,0] 
                 ;  X=[A+B,C,D,0] )
        ;  ( B=C -> X=[A,B+C,D,0]
                 ;  ( C=D -> X=[A,B,C+D,0]
                          ;  X=[A,B,C,D] ))),
  maplist(is,Y,X).

这只是根据您的规范写出案例。我们不必在每次添加两个变量时手动调用is,而是用+象征性地写下总和,最后通过maplist为结果的每个元素一次调用is .

【讨论】:

  • 您能否解释一下您的代码,尤其是地图列表部分。
  • 不客气。 :) 如果不知道长度可能会更难。
【解决方案2】:

这里是任意长度列表的解决方案,并且在没有append 的情况下一次性完成。 (但对我来说,这是一个难得的机会!)

主谓词分派给一个助手,该助手计算最后要添加的零的数量:

merge(List, Merged) :-
    merge(List, 0, Merged).

helper 的重要子句合并两个相邻的相等值。它还会增加要在末尾添加的零的计数器:

merge([X, X | Xs], ExtraZeros, [Sum | MergedRest]) :-
    !,
    Sum is X + X,
    merge(Xs, s(ExtraZeros), MergedRest).

否则,复制元素直到我们到达列表的末尾:

merge([X | Xs], ExtraZeros, [X | Ys]) :-
    merge(Xs, ExtraZeros, Ys).

在列表末尾,根据需要生成零:

merge([], ExtraZeros, ZeroList) :-
    length_zerolist(ExtraZeros, ZeroList).

length_zerolist(0, []).
length_zerolist(s(N), [0 | Zeros]) :-
    length_zerolist(N, Zeros).

问题的测试:

?- merge([4, 4, 0, 0], Merged).
Merged = [8, 0, 0, 0].

?- merge([4, 4, 8, 0], Merged).
Merged = [8, 8, 0, 0].

?- merge([4, 4, 0, 2], Merged).
Merged = [8, 0, 2, 0].

?- merge([0, 0, 2, 2], Merged).
Merged = [0, 4, 0, 0].

更长的列表:

?- merge([0, 1, 1, 2, 3, 3, 4, 4, 5], Merged).
Merged = [0, 2, 2, 6, 8, 5, 0, 0, 0].

【讨论】:

  • 感谢您的回答。你能解释一下这是什么吗:s(N) 和 s(ExtraZeros)。我以前在序言中从未见过这种情况。 :)
  • @ReemaQKhan 当merge/3 开始工作时,它的第二个参数是0。然后在求和的情况下,0 变成s(0),如果没有求和,则保持0。然后s(0) 变成s(s(0)) 等等,通常ExtraZeros 变成s(ExtraZeros) 以防求和被执行,否则保持不变。如果我们计算该复合项中嵌套的s 的数量,我们会发现它的深度与我们所做的求和的数量相同。这被称为 Peano 算术,或一元计数(相对于二进制或十进制)。
  • 这比我的临时答案要好得多。 :) 也简单明了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-15
  • 2022-09-30
相关资源
最近更新 更多