List 如何找到术语列表的最小值?

List 如何找到术语列表的最小值?,list,prolog,minimum,List,Prolog,Minimum,我有一个术语列表如下 [t('L', 76), t('I', 73), t('V', 86), t('E', 69)] 我想在prolog中编写一个谓词,这样它将返回具有最小秒值的项。i、 e.从上面的列表中,它应该返回t('e',69) 下面是我试过的。但这是行不通的 minChar(L, Min) :- setof(t(_, A), member(t(_, A), L), Li), Li = [Min|_]. 这是它为上述输入提供的输出 ?- minChar([t('L'

我有一个术语列表如下

[t('L', 76), t('I', 73), t('V', 86), t('E', 69)]
我想在prolog中编写一个谓词,这样它将返回具有最小秒值的项。i、 e.从上面的列表中,它应该返回
t('e',69)

下面是我试过的。但这是行不通的

minChar(L, Min) :-
    setof(t(_, A), member(t(_, A), L), Li),
    Li = [Min|_].
这是它为上述输入提供的输出

?- minChar([t('L', 76), t('I', 73), t('V', 86), t('E', 69)], Min).
Min = t(_G14650, 69) ;
Min = t(_G14672, 73) ;
Min = t(_G14683, 76) ;
Min = t(_G14661, 86).

正如潜伏者所说,谓词不能以大写字母开头,所以首先修复它

这里有两个基本问题:首先,第二行中的两个下划线表示不同的变量,因此
setof/3
不知道您希望在模板和
member/2
调用中使用相同的变量

第二,setof对结果进行排序(这就是为什么可以像这样提取最小值),但按照构建模板的方式,它会对结果进行错误排序。swi prolog中的排序使用,在您的例子中,您对类型为
t(A,B)
的复合项进行排序,其中A是原子,B是数字。这将首先按字母顺序在A上排序,然后在B上排序,这不是您想要的,您想要在B上排序

如果要使用与术语本身不同的键对事物进行排序,这里的标准技巧是提取所需的键,将其与
(-)/2
函子绑定,然后对其进行排序。因此,就你的例子而言,这应该是可行的:

minChar(L, Min) :- 
  setof(B-t(A, B), member(t(A, B), L), Li),
  Li = [_-Min|_].
请记住,在Prolog中,当你说
X-Y
时,你实际上并没有做任何减法运算,即使看起来你是。您只需使用
(-)/2
函子将X和Y绑定在一起。它只在您明确要求它进行减法运算时才进行减法运算,但使用了一些强制算术运算的运算符(例如,
=:=
is
)。这就是为什么Prolog中
1+1=2
为false的原因,因为
=
是一个统一运算符,不进行任何算术计算

需要明确的是:您不必为此使用
-
,您可以使用任何您喜欢的函子。但这是传统的使用负函子来处理这类事情


编辑:另外,
setof/3
将回溯模板中未找到的任何自由变量,并且由于两个下划线不引用相同的自由变量,它将回溯第二个下划线的所有可能赋值,然后丢弃该结果并为第一个下划线指定新的自由变量。这就是为什么你可以回溯结果,得到一堆你不知道它们来自哪里的匿名变量

正如潜伏者所说,谓词不能以大写字母开头,所以请先解决这个问题

这里有两个基本问题:首先,第二行中的两个下划线表示不同的变量,因此
setof/3
不知道您希望在模板和
member/2
调用中使用相同的变量

第二,setof对结果进行排序(这就是为什么可以像这样提取最小值),但按照构建模板的方式,它会对结果进行错误排序。swi prolog中的排序使用,在您的例子中,您对类型为
t(A,B)
的复合项进行排序,其中A是原子,B是数字。这将首先按字母顺序在A上排序,然后在B上排序,这不是您想要的,您想要在B上排序

如果要使用与术语本身不同的键对事物进行排序,这里的标准技巧是提取所需的键,将其与
(-)/2
函子绑定,然后对其进行排序。因此,就你的例子而言,这应该是可行的:

minChar(L, Min) :- 
  setof(B-t(A, B), member(t(A, B), L), Li),
  Li = [_-Min|_].
请记住,在Prolog中,当你说
X-Y
时,你实际上并没有做任何减法运算,即使看起来你是。您只需使用
(-)/2
函子将X和Y绑定在一起。它只在您明确要求它进行减法运算时才进行减法运算,但使用了一些强制算术运算的运算符(例如,
=:=
is
)。这就是为什么Prolog中
1+1=2
为false的原因,因为
=
是一个统一运算符,不进行任何算术计算

需要明确的是:您不必为此使用
-
,您可以使用任何您喜欢的函子。但这是传统的使用负函子来处理这类事情


编辑:另外,
setof/3
将回溯模板中未找到的任何自由变量,并且由于两个下划线不引用相同的自由变量,它将回溯第二个下划线的所有可能赋值,然后丢弃该结果并为第一个下划线指定新的自由变量。这就是为什么你可以回溯结果,得到一堆你不知道它们来自哪里的匿名变量

您也可以自己编写
minChar
谓词,而不是使用在O(n log n)(至少)中运行的
setof

minChar([X],X) :-
    !.
minChar([t(_,V1)|T],t(A2,V2)) :-
    minChar(T,t(A2,V2)),
    V2 < V1,
    !.
minChar([X|_],X).

这是因为Prolog总是首先按照定义的顺序执行谓词。它只会在您到达空列表案例(列表末尾)时发生。遗嘱签署后,找到较小值的几率将显著降低。

您也可以自己编写一个
minChar
谓词,而不是使用运行在O(n log n)(至少)中的
setof

minChar([X],X) :-
    !.
minChar([t(_,V1)|T],t(A2,V2)) :-
    minChar(T,t(A2,V2)),
    V2 < V1,
    !.
minChar([X|_],X).

这是因为Prolog总是首先按照定义的顺序执行谓词。它只会在您到达空列表案例(列表末尾)时发生。在遗嘱之后,找到较小值的几率会显著降低。

你是Prolog的初学者,所以试着想想Prolog

列表的最小值是多少?此列表中的一个元素,此列表中没有其他元素比它小。 这样你就可以写作了

my_min(L, Min) :-
    member(Min, L),
    \+((member(X, L), X < Min)).
my_min(L,min):-
成员(最小,L),
\+((成员(X,L),X
有人会说:“这没有效率!”。是的,但我认为这是学习序言的好方法

你应该是艾达
min_of_list(L, t(X,Y)) :-
    member(t(X, Y), L),
    \+((member(t(_, Z), L), Z < Y)).