prolog中的交换函数,无限循环

prolog中的交换函数,无限循环,prolog,swi-prolog,Prolog,Swi Prolog,我试图在prolog中创建一个swap函数,但我最终得到了一个无限循环,我尝试使用trace() 这个函数的一个例子是swap(4,3,[“You”,“Are”,“Awesome”,“thank”,“You”],“SwappedList”) 输出为 [“你”、“是”、“谢谢”、“棒极了”、“你”] 在跟踪输出中,显示问题在删除中,因为它是failure和redesthesplit /* Getting the nth element of the list*/ n_thelement(1, [

我试图在
prolog
中创建一个swap函数,但我最终得到了一个
无限循环
,我尝试使用
trace()

这个函数的一个例子是swap(4,3,[“You”,“Are”,“Awesome”,“thank”,“You”],“SwappedList”)

输出为

[“你”、“是”、“谢谢”、“棒极了”、“你”]

在跟踪输出中,显示问题在删除中,因为它是
failure
redes
the
split

/* Getting the nth element of the list*/

n_thelement(1, [Head|_], Head).
n_thelement(N, [_|Tail], Item):-
    NewN is N-1,
    n_thelement(NewN, Tail, Item).

/* Deleting the element of the desired Nth element*/

delete(X, [X|Tail], Tail).
delete(X, [Head|Tail], [Head|Item]):-
    delete(X, Tail, Item).

/* Adding the deleted element to the beginning of the list*/

append([], Element, Element).
append([Head], Element, [Head|Element]).

swap(X, X, List, List).

swap(X, Y, List, NList):-
    n_thelement(X, List, Num1),
    n_thelement(Y, List, Num2),
    split(X, List, B1, A1),
    delete(Num1, A1, L1),
    append([Num2], L1, NList1),
    append(B1, NList1, NList2),
    split(Y, NList2, B2, A2),
    delete(Num2, A2, L2),
    append([Num1], L2, NList3),
    append(B2, NList3, NList).
    
split(1, [Head|Tail], Head, Tail).

split(N, [Old_List|New_List], Old_List, New_List):-
    NewN is N -1,
    split(NewN, _, Old_List, New_List).

如果我正确理解了你的问题陈述,给出了列表中的索引M和N,使得M 我会首先使指数为零相对,而不是1相对,因为这使数学更容易一些

因此,您需要将列表分成5个部分,其中3个是任意长度的列表,其中两个是要交换的列表项:

  • As
    :列表的引入前缀。它的长度是米
  • B
    :要交换的第一项
  • Cs
    :列表的中间部分。其长度为N-(M+1)
  • D
    :要交换的第二项
  • Es
    :列表的后缀/剩余部分。它是任意长度的
append/3
有助于列表的解构和重建,使实际交换变得容易。你有3个箱子

  • 首先,两个指数相同的特殊情况,在这种情况下,没有工作要做:

    swap( M, M, Ls, Ls ).
    
  • 第二,指数无序的情况,在这种情况下,我们只是递归地交换它们以使它们有序:

    swap( M, N, Ls, Rs ) :- M > N, swap(N,M,Ls,Rs).
    
  • 第三,一般情况:

    swap( M, N, Ls, Rs ) :-      % if the 2 indices differ
      M < N,                     % - and are in order
      M >= 0,                    % - and M is greater than or equal to zero
      N >= 0,                    % - and N is greater than or equal to zero
      X is N - (M+1),            % - compute the length of the middle segment
      length( As, M  ),          % - construct an empty, unbound list of length M, the length of the prefix
      length( Cs, X ),           % - and construct an empty, unbound list of that length
      append( As, [B|T1], Ls),   % - get the prefix (As) and the first item (B) to be swapped
      append( Cs, [D|Es], T1),   % - get the middle segment (Cs), the second item (D) to be swapped, and the suffix (Es)
      append( As, [D|Cs], T2),   % - concatenate As, D, and Cs, then...
      append( T2, [B|Es], Rs )   % - concatenate that with B and the suffix
      .                          % Easy!
    
    swap(M,N,Ls,Rs):-%如果两个指数不同
    M=0,%-且M大于或等于零
    N>=0,%-且N大于或等于零
    X是N-(M+1),%-计算中间段的长度
    长度(As,M),%-构造一个空的、未绑定的长度为M的列表,即前缀的长度
    长度(Cs,X),%-并构造该长度的空的未绑定列表
    追加(As[B | T1],Ls),%-获取前缀(As)和要交换的第一项(B)
    追加(Cs,[D|Es],T1),%-获取中间段(Cs)、要交换的第二项(D)和后缀(Es)
    追加(As[D | Cs],T2),%-连接As、D和Cs,然后。。。
    附加(T2,[B|Es],Rs)%-将其与B和后缀连接起来
    .                          % 容易的!
    

您可以定义一个谓词,将列表的第i项替换为另一项:

replace(Index, [Old|Rest], [New|Rest], Old, New) :- Index == 0, !.
replace(Index, [First|Rest], [First|NewRest], Old, New) :-
   Index > 0,
   Previous is Index - 1,
   replace(Previous, Rest, NewRest, Old, New).
示例:

?- replace(1, [a,b,c,d,e], List1, Old1, x).
List1 = [a, x, c, d, e],
Old1 = b.

?- replace(1, [a,b,c,d,e], List1, Old1, New1).
List1 = [a, New1, c, d, e],
Old1 = b.

?- replace(4, [a,b,c,d,e], List2, Old2, New2).
List2 = [a, b, c, d, New2],
Old2 = e.
?- swap(3, 2, ["You", "Are", "Awesome", "thank", "You"], L).
L = ["You", "Are", "thank", "Awesome", "You"].

?- swap(1, 4, [a,b,c,d,e], L).
L = [a, e, c, d, b].

?- swap(0, 3, [a,b,c,d,e], L).
L = [d, b, c, a, e].

?- swap(1, 0, [a,b,c,d,e], L).
L = [b, a, c, d, e].

?- swap(2, 2, [a,b,c,d,e], L).
L = [a, b, c, d, e].

?- swap(3, 9, [a,b,c,d,e], L).
false.
然后,使用此谓词,您可以定义:

swap(I, J, OldList, NewList) :-
   replace(I, OldList, List, X, Y),
   replace(J, List, NewList, Y, X).
示例:

?- replace(1, [a,b,c,d,e], List1, Old1, x).
List1 = [a, x, c, d, e],
Old1 = b.

?- replace(1, [a,b,c,d,e], List1, Old1, New1).
List1 = [a, New1, c, d, e],
Old1 = b.

?- replace(4, [a,b,c,d,e], List2, Old2, New2).
List2 = [a, b, c, d, New2],
Old2 = e.
?- swap(3, 2, ["You", "Are", "Awesome", "thank", "You"], L).
L = ["You", "Are", "thank", "Awesome", "You"].

?- swap(1, 4, [a,b,c,d,e], L).
L = [a, e, c, d, b].

?- swap(0, 3, [a,b,c,d,e], L).
L = [d, b, c, a, e].

?- swap(1, 0, [a,b,c,d,e], L).
L = [b, a, c, d, e].

?- swap(2, 2, [a,b,c,d,e], L).
L = [a, b, c, d, e].

?- swap(3, 9, [a,b,c,d,e], L).
false.