好吧,在过去的几个小时里,我一直在尝试将给定列表的第二项与其倒数第二项(倒数第二项)交换。给名单[a,b,c,d,e,f]
,我要拿[a,e,c,d,b,f]
。例如:
correct(List1,X,List2)
?-correct([a,y,b,c,d,e,x,f],x,List2).
List2[a,x,b,c,d,e,y,f].
List1
是我要交换第二个和倒数第二个(倒数第二个)元素的列表。X
是倒数第二个元素。List2
是带有交换元素的新列表。
mbratch 和 CapelliC 发布的解决方案在以下基本情况下均失败:
?- correct([a,y], X, List2).
false.
以下解决方案处理了这种基本情况,并且不依赖于可能可用或可能不可用的列表谓词。它遍历列表一次,比其他两种解决方案效率更高:
correct([PreLast, Second], Second, [Second, PreLast]) :-
!.
correct([First, Second, Last], Second, [First, Second, Last]) :-
!.
correct([First, Second| InRest], PreLast, [First, PreLast| OutRest]) :-
correct_aux(InRest, Second, PreLast, OutRest).
correct_aux([PreLast, Last], Second, PreLast, [Second, Last]) :-
!.
correct_aux([Other| InRest], Second, PreLast, [Other| OutRest]) :-
correct_aux(InRest, Second, PreLast, OutRest).
示例查询:
?- correct([a,b], X, List).
X = b,
List = [b, a].
?- correct([a,b,c], X, List).
X = b,
List = [a, b, c].
?- correct([a,b,c,d], X, List).
X = c,
List = [a, c, b, d].
?- correct([a,b,c,d,e], X, List).
X = d,
List = [a, d, c, b, e].
这将适用于长度4
或更大的列表:
correct( [H1|[H2|T1]], X, [H1|[X|T2]] ) :-
reverse(T1, [HR|[X|TR]]),
reverse([HR|[H2|TR]], T2).
| ?- correct( [1,2,3,4,5,6], X, L ).
L = [1,5,3,4,2,6]
X = 5
(1 ms) yes
| ?-
您可以通过添加另外两个谓词来包含较短的情况,如果这是意图,则将解决方案带到:
correct( [A,X], X, [X,A] ).
correct( [A,X,B], X, [A,X,B] ).
correct( [H1|[H2|T1]], X, [H1|[X|T2]] ) :-
reverse(T1, [HR|[X|TR]]),
reverse([HR|[H2|TR]], T2).
另一个可用的内置函数是 append/2:
3 ?- [user].
correct(L, X, R) :- append([[A,B],C,[X,E]], L), append([[A,X],C,[B,E]], R).
|:
% user://2 compiled 0.02 sec, 2 clauses
true.
4 ?- correct( [1,2,3,4,5,6], X, L ).
X = 5,
L = [1, 5, 3, 4, 2, 6] ;
我喜欢 mbratch one (+1),也许这个解决方案更直观。