如何更改列表中两个元素的位置(PROLOG)

时间:2017-06-13 01:01:38

标签: prolog

谓词change_pos(E1, E2,Lin,Lout).

Lin有任意数量的元素,我需要将E1的所有出现更改为E2,反之亦然。并返回Lout

我在考虑做这样的事情:

change(X, Y, [], []).
change(X, Y, [X|L], [Y,L1]):- change(X,Y,L,L1).
change(X, Y, [Z|L], [Z,L1]:- X \== Z, change(X,Y,L,L1).

但这种方式不会刷两个列表

2 个答案:

答案 0 :(得分:4)

我想,因为这是家庭作业,所以学习列表处理和递归是一项练习。但在Prolog中,在列表中依次处理每个术语的常用工具是maplist

% Rule for changing one element
change_element(X, Y, X, Y).
change_element(X, Y, Y, X).
change_element(X, Y, Z, Z) :- dif(X, Z), dif(Y, Z).

% Rule for changing a list
change(X, Y, L1, L2) :-
    maplist(change_element(X, Y), L1, L2).

哪个收益率:

?- change(a, b, [a,b,c,b,a], L).

L = [b, a, c, a, b] ? ;

no
?-

<小时/> 对于确定解决方案,您可以使用if_/3

change1(X, Y, A, B) :-
    if_(=(Y, A), B = X, A = B).
change2(X, Y, A, B) :-
    if_(=(X, A), B = Y, change1(X, Y, A, B)).

change(X, Y, L1, L2) :- maplist(change2(X, Y), L1, L2).

哪个收益率:

?- change(a, b, [a,b,c,b,a], L).

L = [b, a, c, a, b].

?-

答案 1 :(得分:2)

你几乎就在那里。你的基本情况(空列表)和你的第二个规则(X的交换Y)基本上没问题(除了评论中指出的细节)。但是,您缺少反之亦然的规则(Y的交换X)。在您的上一条规则中,您可能希望确保Z不仅与X不同,还与Y不同,否则Z将受到第二或第三规则的约束。

change(X, Y, [], []).
change(X, Y, [X|L], [Y|L1]) :-
   change(X,Y,L,L1).
change(X, Y, [Y|L], [X|L1]) :-   % <- vice versa case
   change(X,Y,L,L1).
change(X, Y, [Z|L], [Z|L1]) :-
      dif(X,Z),                  % <- neither X=Z
      dif(Y,Z),                  % <- nor vice versa
      change(X,Y,L,L1).

以下是一些示例查询。 使用 [1,2,3,4] 交换 1 之后 2 的内容是什么样,反之亦然?

   ?- change(1,2,[1,2,3,4],L).
L = [2,1,3,4] ? ;
no

在使用 [2,1,3,4] 交换 1 之前, 2 的内容是什么样的反之亦然?

   ?- change(1,2,L,[2,1,3,4]).
L = [1,2,3,4] ? ;
no

如果结果列表是 [1,2,3,4] ,则 [2,1,3,4] 中已交换了哪些元素?

   ?- change(X,Y,[1,2,3,4],[2,1,3,4]).
X = 1,
Y = 2 ? ;
X = 2,
Y = 1 ? ;
no