完成一本从书上开始的练习,我想要一个列表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).
答案 0 :(得分:1)
这里有两个问题:
append
加上[(H1, H2)]
和[]
给我们带来了我们可以事先知道的结果:Y
也将是[(H1, H2)]
; X
做任何事情,因此您只处理第一个元素,然后丢弃该元素。因此,您的谓词将只处理第一个元素,并使用该元组创建一个列表,例如:
?- switch([1,2,3], Y).
Y = [(0, 2)].
实际上,这里我们根本不需要append/3
:我们有两个参数,如果前一个参数是非空的,则后者也是非空的,反之亦然。因此,我们的递归子句具有以下形状:
switch([], []).
switch([H|T], [(H1, H2)|TT]) :-
%% ...
因此,我们需要指定H
与H1
和H2
之间的关系; T
和TT
(“元组列表”的其余元素)。对于H
,这已经实现了H1 is H-1
和H2 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).