微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决prolog中的交换函数,无限循环

我试图在 prolog 中创建一个交换函数,但我最终得到了一个 infinite loop,我尝试使用 trace() 调试它

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

输出

[“你”、“是”、“谢谢”、“真棒”、“你”]

在跟踪输出中,它显示问题在于删除,因为它是 failingredoes 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,Item).

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

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

swap(X,X,List,List).

swap(X,Y,NList):-
    n_thelement(X,Num1),n_thelement(Y,Num2),split(X,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).

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

解决方法

如果我正确理解您的问题陈述,将索引分配给列表 M 和 N,使得 M

我首先将索引设为零相关而不是 1 相关,因为这会使数学更容易一些。

因此,您想将列表分成 5 部分,其中 3 个本身是任意长度的列表,其中两个是要交换的列表条目:

  • As:列表的导入前缀。它的长度为 M。
  • B:要交换的第一个项目。
  • Cs:列表的中间部分。它的长度为 N - (M+1)。
  • D:要交换的第二项。
  • Es:列表的后缀/余数。长度不限。

append/3 对列表的解构和重建很有用,使实际的交换变得容易。您有 3 个案例。

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

    swap( M,M,Ls,Ls ).
    
  • 其次,索引乱序的情况,在这种情况下,我们只是递归地交换它们以将它们排序:

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

    swap( M,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!
    
,

您可以定义一个谓词来替换列表中的i项:

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

示例:

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

?- replace(1,New1).
List1 = [a,New1,Old1 = b.

?- replace(4,List2,Old2,New2).
List2 = [a,New2],Old2 = e.

然后,使用这个谓词,你可以定义:

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

示例:

?- swap(3,2,["You","Are","Awesome","thank","You"],L).
L = ["You","You"].

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

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

?- swap(1,L).
L = [b,e].

?- swap(2,e].

?- swap(3,9,L).
false.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。