我正在尝试查找列表的最小值(作为学习体验,因此没有min
)。
我的方法如下:
minimo([X], X).
minimo([X,Y|Tail], N):-
(X > Y, minimo([Y,Tail], Y));
(X <= Y, minimo([X,Tail], X)).
这给了我以下错误:
语法错误:操作员期望
所以我的问题是:
提前致谢。
答案 0 :(得分:4)
您的计划中有几个错误:
正如Joe Lehmann所指出的,没有'<='/2
。必须是'=<'/2
。
当你递归调用minimo/2
时,你构造错误的列表。而不是[Y,Tail]
使用[Y|Tail]
。否则,您将获得一个列表作为第二个元素。
将minimo/2
的递归调用的第二个参数绑定到Y
或X
。相反,它必须绑定到N
。否则,您的N
将永远不会被实例化。
您可以通过添加剪辑或使用if-then-else('->'
+ ;
)来进一步改进您的计划:
minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
( X > Y ->
minimo([Y|Tail], N)
;
minimo([X|Tail], N)
).
答案 1 :(得分:4)
除了已发布的其他版本之外,还要考虑没有if-then-else的版本,并使用更具描述性的关系名称(将列表与其最小值相关联):
list_min([L|Ls], Min) :- list_min(Ls, L, Min).
list_min([], Min, Min).
list_min([L|Ls], Min0, Min) :-
Min1 is min(L, Min0),
list_min(Ls, Min1, Min).
这种模式称为 fold (从左侧开始),我们可以使用`foldl / 4:
等效地编写它list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
min_(A, B, Min) :- Min is min(A, B).
示例查询:
?- list_min([1,0,2], Min).
Min = 0.
请注意,这不是真正的关系,并且由于使用了低级算术而无法在所有方向上使用。例如,如果我们尝试在另一个方向上使用它,我们得到:
?- list_min([X,Y], 3). ERROR: is/2: Arguments are not sufficiently instantiated
要使其成为真正的解决方案,请使用约束,例如clpfd和clpq。例如,对于整数的解决方案:
:- use_module(library(clpfd)).
list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).
min_(A, B, Min) :- Min #= min(A, B).
这适用于所有方向:
?- list_min([X,Y], 3).
X in 3..sup,
3#=min(Y, X),
Y in 3..sup.
答案 2 :(得分:3)
语法错误是,因为Prolog中的数量少于或等于=&lt;,不是&lt; =。
我认为这种方法可行,但你真的应该避免;在一个条款中。把它分成两个条款。
另外我认为你想在递归中做[X | Tail]而不是[X,Tail]
答案 3 :(得分:2)
min([H|T], Min) :- min(T, H, Min).
min([], Min, Min).
min([H|T], Min, Min1) :-
( H < Min
-> min(T, H, Min1)
; min(T, Min, Min1) ).