Здесь есть две проблемы:
append
ing [(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
Здесь мы можем запрашивать только в одном направлении: если мы объединяем список из двух кортежей со вторым аргументом, то Prolog не может получить элементы впервый список.Однако мы можем определить ограничения между этими элементами, и в результате мы можем запросить в нескольких направлениях:
:- use_module(<b>library(clpfd)</b>).
switch([], []).
switch([H|T], [(H1, H2)|TT]) :-
H1 <b>#=</b> H-1,
H2 <b>#=</b> H+1,
switch(T, TT).
Теперь мы можем запросить, например, с помощью:
?- switch(L, [(1, A), (3, 5), (C, 7)]).
L = [2, 4, 6],
A = 3,
C = 5.
Задача, которую мы решаем, является типичной «задачей картирования».Таким образом, мы можем " удалить наш шаблон " и использовать maplist/3
:
:- use_module(library(clpfd)).
switch_tuple(H, (H1, H2)) :-
H1 #= H-1,
H2 #= H+1.
switch(L1, L2) :-
<b>maplist</b>(switch_tuple, L1, L2).