Prolog 序言:如何查找和删除最小列表元素?

Prolog 序言:如何查找和删除最小列表元素?,prolog,clpfd,Prolog,Clpfd,我不熟悉Prolog 我需要帮助编写一个谓词来查找和删除列表中的最小元素 多谢各位 让我帮你搜索一下 无论如何,有一个很好的谓词 ?- min_list([1,2,2,3],X). X = 1. 下面是一个如何从列表中删除某些元素的小示例(请注意,所有2s都消失了): 如果只想删除元素的第一次,请使用: 所以你的最终答案可能是这样的: delete_min(A, C) :- min_list(A, B), select(B, A, C), !. 及 同样,只需在列表上使用结构递归。

我不熟悉Prolog

我需要帮助编写一个谓词来查找和删除列表中的最小元素


多谢各位

让我帮你搜索一下

无论如何,有一个很好的谓词

?- min_list([1,2,2,3],X).
X = 1.
下面是一个如何从列表中删除某些元素的小示例(请注意,所有
2
s都消失了):

如果只想删除元素的第一次,请使用:

所以你的最终答案可能是这样的:

delete_min(A, C) :-
  min_list(A, B),
  select(B, A, C), !.


同样,只需在列表上使用结构递归。列表由节点
[H | T]
构成,即具有两个字段的复合数据结构-head,
H
,tail,
T
。Head是节点中保存的数据(列表元素),而
T
是列表的其余部分

我们通过滚动列表找到最小元素,同时保留一个额外的数据-到目前为止看到的所有元素中的最小元素:

minimum_elt([H|T],X):- minimum_elt(T,H,X).
空列表案例没有定义-空列表没有最小元素

minimum_elt([],X,X).
如果列表中没有更多的元素,那么到目前为止我们得到的就是答案

minimum_elt([A|B],M,X):- 
这里有两种情况:
A
,或者其他情况:

    A < M, minimum_elt(B,A,X).

minimum_elt([A|B],M,X):- 

    A >= M, minimum_elt(B,M,X).
A=M,最小值(B,M,X)。
没什么要说的了,这就完成了程序


编辑:除此之外,您还希望删除该元素。这改变了一切。嗯,一个明显的方法是首先找到最小elt,然后删除它。我们必须再次比较所有元素,这次是与之前找到的最小元素进行比较。我们能一次扫描完成吗

在Lisp中,我们可以使用。要从列表中删除任何元素,我们只需通过外科手术重置前一个节点的尾部指针,以指向删除后的下一个节点。然后使用这种方法,我们将扫描输入列表一次,将对前一个节点的引用保持到目前为止找到的最小元素,并在找到越来越小的元素时交换它。当我们到达列表的末尾时,我们只需通过手术移除最小的节点

但在Prolog中,我们无法重置内容。Prolog是一种一次性设置的语言。看来我们需要把名单翻两遍。。。或者,我们可以试着非常聪明地处理它,并在进行过程中构建所有可能的列表,在每次找到最小元素的新候选项时对它们进行排序

rem_min([A|B],L):-
    % two possibilities: A is or isn't the minimum elt
    rem_min(B,A,([A|Z],Z,Z),L).

rem_min([],A,(With,Without,Tail),L):- Tail = [],
    % A is indeed the minimal element
    L = Without.

rem_min([H|T],A,(With,Without,Tail),L):- H >= A, Tail=[H|Z],
    rem_min(T,A,(With,Without,Z),L).

rem_min([H|T],A,(With,Without,Tail),L):- H < A,  % use this H
    copy_the_list(With,Tail,W2,T2),              % no good - quadratic behaviour
    Tail=[H|Z], T2=Z,
    rem_min(T,A,(With,W2,Z),L).

copy_the_list([A|B],T,[A|C],C):- var(B), !, T=B.            % fresh tail
copy_the_list([A|B],T,[A|C],T2):- copy_the_list(B,T,C,T2).
rem|min([A|B],L):-
%两种可能性:A是或不是最低elt
rem|min(B,A,([A|Z],Z,Z),L)。
rem_min([],A,(带尾,不带尾),L):-Tail=[],
%A确实是最小的元素
L=没有。
rem|min([H | T],A,(带,不带尾),L):-H>=A,Tail=[H | Z],
rem_min(T,A,(有,无,Z),L)。
rem_min([H | T],A,(有尾,无尾),L):-H

看来我们无法避免第二次,但至少我们可以避免所有多余的比较:

rem_min([A|B],L):- N=[A|_], rem_min(B,A,N,[N|Z],Z,L).

rem_min([],_A,N,L2,Z,L):- Z=[], N=[_,1], % finalize the minimal entry
    scan(L2,L).
rem_min([H|T],A,N,L2,Z,L):- H >= A, Z=[H|Z2], rem_min(T,A,N,L2,Z2,L).
rem_min([H|T],A,N,L2,Z,L):- H < A,       % use this H
    N2=[H|_], N=[_],                     % finalize the non-minimal entry
    Z=[N2|Z2], rem_min(T,H,N2,L2,Z2,L).

scan( [], []).
scan( [[_,1]|B],C):- !, scan(B,C).       % step over the minimal element
scan( [[A]|B],[A|C]):- !, scan(B,C).     % previous candidate
scan( [A|B], [A|C]):- !, scan(B,C).    
rem|min([A|B],L):-N=[A|u],rem|min(B,A,N[N|Z],Z,L)。
rem_min([],_A,N,L2,Z,L):-Z=[],N=[[u,1],%完成最小条目
扫描(L2,L)。
rem|min([H|T],A,N,L2,Z,L):-H>=A,Z=[H|Z2],rem|min(T,A,N,L2,Z2,L)。
rem|min([H|T],A,N,L2,Z,L):-H
如果所有列表项都是整数,我们可以使用

我们定义
zmin\u deleted/2
, ,及:

请注意,
zmin_deleted/2
也适用于“其他方向”:


>不幸的是,人们很快就结束了一个他们不喜欢的问题。它可能因为没有OP进行研究的明显迹象而关闭。
    A < M, minimum_elt(B,A,X).

minimum_elt([A|B],M,X):- 

    A >= M, minimum_elt(B,M,X).
rem_min([A|B],L):-
    % two possibilities: A is or isn't the minimum elt
    rem_min(B,A,([A|Z],Z,Z),L).

rem_min([],A,(With,Without,Tail),L):- Tail = [],
    % A is indeed the minimal element
    L = Without.

rem_min([H|T],A,(With,Without,Tail),L):- H >= A, Tail=[H|Z],
    rem_min(T,A,(With,Without,Z),L).

rem_min([H|T],A,(With,Without,Tail),L):- H < A,  % use this H
    copy_the_list(With,Tail,W2,T2),              % no good - quadratic behaviour
    Tail=[H|Z], T2=Z,
    rem_min(T,A,(With,W2,Z),L).

copy_the_list([A|B],T,[A|C],C):- var(B), !, T=B.            % fresh tail
copy_the_list([A|B],T,[A|C],T2):- copy_the_list(B,T,C,T2).
rem_min([A|B],L):- N=[A|_], rem_min(B,A,N,[N|Z],Z,L).

rem_min([],_A,N,L2,Z,L):- Z=[], N=[_,1], % finalize the minimal entry
    scan(L2,L).
rem_min([H|T],A,N,L2,Z,L):- H >= A, Z=[H|Z2], rem_min(T,A,N,L2,Z2,L).
rem_min([H|T],A,N,L2,Z,L):- H < A,       % use this H
    N2=[H|_], N=[_],                     % finalize the non-minimal entry
    Z=[N2|Z2], rem_min(T,H,N2,L2,Z2,L).

scan( [], []).
scan( [[_,1]|B],C):- !, scan(B,C).       % step over the minimal element
scan( [[A]|B],[A|C]):- !, scan(B,C).     % previous candidate
scan( [A|B], [A|C]):- !, scan(B,C).    
:- use_module(library(clpfd)).
zmin_deleted(Zs1,Zs0) :-
   same_length(Zs1,[_|Zs0]),
   maplist(#=<(Min),Zs1),
   select(Min,Zs1,Zs0).
?- zmin_deleted([3,2,7,8],Zs).
  Zs = [3,7,8]
; false.

?- zmin_deleted([3,2,7,8,2],Zs).
  Zs = [3,  7,8,2]
; Zs = [3,2,7,8  ]
; false.
?- zmin_deleted(Zs,[3,2,7,8]).
  _A in inf..2, Zs = [_A, 3, 2, 7, 8]
; _A in inf..2, Zs = [ 3,_A, 2, 7, 8]
; _A in inf..2, Zs = [ 3, 2,_A, 7, 8]
; _A in inf..2, Zs = [ 3, 2, 7,_A, 8]
; _A in inf..2, Zs = [ 3, 2, 7, 8,_A]
; false.