2

好吧,在过去的几个小时里,我一直在尝试将给定列表的第二项与其倒数第二项(倒数第二项)交换。给名单[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是带有交换元素的新列表。
4

3 回答 3

2

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].
于 2013-09-03T23:34:16.007 回答
1

这将适用于长度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).
于 2013-09-03T17:37:10.043 回答
1

另一个可用的内置函数是 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),也许这个解决方案更直观。

于 2013-09-03T19:21:59.413 回答