Prolog-更改列表元素

时间:2019-02-05 18:16:18

标签: list prolog

完成一本从书上开始的练习,我想要一个列表X并更改其元素,以便对于某些[H|X]的新列表Y将具有HEAD元素为(H-1,H+1)

类似的东西:

X=[1,20,300] --> Y=[(0,2),(19,21),(299,301)]

到目前为止,我所添加的是第一个元素,但随后返回了一些奇怪的“ _number”。我到目前为止所拥有的:

switch([], []).
switch([H|X], Y) :-
   H1 is H-1,
   H2 is H+1,
   append([(H1,H2)], [], Y).

1 个答案:

答案 0 :(得分:1)

这里有两个问题:

  1. append加上[(H1, H2)][]给我们带来了我们可以事先知道的结果:Y也将是[(H1, H2)]
  2. 在这种情况下,您不会对结尾X做任何事情,因此您只处理第一个元素,然后丢弃该元素。

因此,您的谓词将只处理第一个元素,并使用该元组创建一个列表,例如:

?- switch([1,2,3], Y).
Y = [(0, 2)].

实际上,这里我们根本不需要append/3:我们有两个参数,如果前一个参数是非空的,则后者也是非空的,反之亦然。因此,我们的递归子句具有以下形状:

switch([], []).
switch([H|T], [(H1, H2)|TT]) :-
    %% ...

因此,我们需要指定HH1H2之间的关系; TTT(“元组列表”的其余元素)。对于H,这已经实现了H1 is H-1H2 is H + 1 . As for T and TT , we just need to continue processing, so we make a recursive call with T and TT `:

switch([], []).
switch([H|T], [(H1, H2)|TT]) :-
    H1 is H-1,
    H2 is H+1,
    switch(T, TT).

使用clpfd

在这里,我们只能在一个方向上进行查询:如果我们用第二个参数统一一个2元组的列表,则Prolog无法派生第一个列表中的元素。但是,我们可以在这些元素之间定义约束,因此,我们可以在多个方向进行查询:

:- use_module(library(clpfd)).

switch([], []).
switch([H|T], [(H1, H2)|TT]) :-
    H1 #= H-1,
    H2 #= H+1,
    switch(T, TT).

我们现在可以使用以下示例进行查询:

?- switch(L, [(1, A), (3, 5), (C, 7)]).
L = [2, 4, 6],
A = 3,
C = 5.

使用maplist/3

我们要解决的任务是典型的“映射任务”。因此,我们可以“ 报废样板”,并使用maplist/3

:- use_module(library(clpfd)).

switch_tuple(H, (H1, H2)) :-
    H1 #= H-1,
    H2 #= H+1.

switch(L1, L2) :-
    maplist(switch_tuple, L1, L2).