我是prolog的新手,我只是在学习列表而且我遇到了this question。答案适用于整数列表。
minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
( X > Y ->
minimo([Y|Tail], N)
;
minimo([X|Tail], N)
).
如何更改此代码以从混合列表中获取最小的int?
这个
sint([a,b,3,2,1],S)
应该给出答案:
S=1
答案 0 :(得分:2)
你可以忽略这个问题,将比较运算符(>)/ 2(实际上是二进制内置谓词)更改为更通用的(@>)/ 2:
minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
( X @> Y ->
minimo([Y|Tail], N)
;
minimo([X|Tail], N)
).
?- minimo([a,b,3,2,1],S).
S = 1.
答案 1 :(得分:1)
您可以编写一个谓词,该谓词返回带有数字的列表并使用上面的minimo / 2谓词:
only_numbers([],[]).
only_numbers([H|T],[H|T1]):-integer(H),only_numbers(T,T1).
only_numbers([H|T],L):- \+integer(H),only_numbers(T,L).
sint(L,S):-only_numbers(L,L1),minimo(L1,S).
答案 2 :(得分:1)
首先,我不认为提议的实现非常优雅:在这里,他们通过每次构建一个新列表来传递最小的找到元素。使用附加参数(我们称之为累加器)通常是要走的路(也可能更有效)。
为了解决这个问题,我们首先必须找到一个整数。我们可以这样做:
sint([H|T],R) :-
integer(H),
!,
sint(T,H,R).
sint([_|T],R) :-
sint(T,R).
所以我们在这里检查 head H
是否为integer/1
。如果是这种情况,我们会调用谓词sint/3
(不要与sint/2
混淆)。否则,我们会使用列表的 tail sint/2
递归调用T
。
现在我们仍然需要定义sint/3
。如果我们到达列表[]
的末尾,我们只返回到目前为止找到的最小值:
sint([],R,R).
否则有两种情况:
head H
是一个整数,小于到目前为止找到的元素,在这种情况下,我们执行递归,将head作为新的当前最小值:
sint([H|T],M,R):
integer(H),
H < M,
!,
sint(T,H,R).
否则,我们只是忽略头部,并使用尾部T
执行递归。
sint([_|T],M,R) :-
sint(T,M,R).
我们可以将递归子句放在if-then-else结构中。与之前定义的谓词一起,完整的程序就是:
sint([H|T],R) :-
integer(H),
!,
sint(T,H,R).
sint([_|T],R) :-
sint(T,R).
sint([],R,R).
sint([H|T],M,R):
(
(integer(H),H < M)
-> sint(T,H,R)
; sint(T,M,R)
).
这种方法的优点是过滤和比较(以获得最小值)是同时完成的,所以我们只在列表上迭代一次。这通常会导致性能提升,因为&#34;控制结构&#34;只执行一次:更多是在迭代中完成,但我们只迭代一次。
我们可以通过过滤器泛型来概括该方法:
filter_minimum(Filter,[H|T],R) :-
Goal =.. [Filter,H],
call(Goal),
!,
filter_minimum(Filter,T,H,R).
filter_minimum(Filter,[_|T],R) :-
filter_minimum(Filter,T,R).
filter_minimum(_,[],R,R).
filter_minimum(Filter,[H|T],M,R) :-
Goal =.. [Filter,H],
(
(call(Goal),H < M)
-> filter_minimum(Filter,T,H,R)
; filter_minimum(Filter,T,M,R)
).
然后你可以用:
来调用它filter_minimum(integer,[a,b,3,2,1],R).
使用integer/1
进行过滤并计算最小值。