【发布时间】:2009-11-02 09:10:11
【问题描述】:
我有一个列表,我需要找到其中最长的一个。如果有多个长度相同,则返回的相同。谢谢。
【问题讨论】:
-
你能写一个 3 位谓词来比较两个列表并“返回”较长的那个吗?
-
嗯,也许吧。稍后我会看的。现在开始讲课。
我有一个列表,我需要找到其中最长的一个。如果有多个长度相同,则返回的相同。谢谢。
【问题讨论】:
这是一个通用谓词,它扫描列表以查找由给定目标定义的单个成员。
select_element(Goal, [Head | Tail], Selected) :-
select_element(Goal, Tail, Head, Selected).
select_element(_Goal, [], Selected, Selected).
select_element(Goal, [Head | Tail], Current, FinalSelected) :-
call(Goal, Head, Current, Selected),
select_element(Goal, Tail, Selected, FinalSelected).
假设你定义了一个谓词
get_bigger_number(N1, N2, N) :-
N is max(N1, N2).
现在你可以执行了:
?- select_element(get_bigger_number, [5, 1, -2, 10, 3.2, 0], Selected).
Selected = 10
所以你现在需要做的就是定义一个谓词get_longer_list(L1, L2, L),
并使用它来代替get_bigger_number/3。
当然,使用像select_element/3 这样的通用谓词可能效率不高。例如,您应该尽量避免多次计算同一个列表的长度,因为这种计算在 Prolog 中很慢(至少如果在 Prolog 中以标准方式实现)。
【讨论】:
请考虑我的方法。
longest([L], L) :-
!.
longest([H|T], H) :-
length(H, N),
longest(T, X),
length(X, M),
N > M,
!.
longest([H|T], X) :-
longest(T, X),
!.
那你可以参考一下:
?- longest([[1]], N).
N = [1] ;
?- longest([[1],[2]], N).
N = [2] .
?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3] ;
?- longest([[1],[2], [3,3,3], [2]], N).
N = [3, 3, 3].
?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] .
?- longest([[1],[2], [3,3,3], [2], [4,4,4,4]], N).
N = [4, 4, 4, 4] ;
你好!
【讨论】:
longest([[1],[2]],[1]) 失败。它应该成功!
我们根据meta-predicate 定义longest/2 max_of_by/3 与length/2 一起使用:
longest(Xss,Ys) :-
max_of_by(Ys,Xss,length).
示例查询:
?- longest([[1],[2]],Xs). % we expect multiple solutions
Xs = [1]
; Xs = [2]. % we _get_ multiple solutions
?- longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],Xs).
Xs = [1,8,2,3,1]. % succeeds deterministically
【讨论】:
这是另一种有效且易于理解的方法。思路是找出列表中所有列表的长度,使用max_list得到最长列表的长度,然后找到一个那么长的列表。这样做的好处是它将返回所有最长长度的列表。
lengths([],[]).
lengths([H|T], [LH|LengthsT]) :-
length(H, LH),
lengths(T, LengthsT).
lengthLongest(ListOfLists, Max) :-
lengths(ListOfLists, Lengths),
max_list(Lengths, Max).
longestList(ListOfLists, Longest) :-
lengthLongest(ListOfLists, Len),
member(Longest, ListOfLists),
length(Longest, Len).
【讨论】:
% Correct again.
longest(LL,LX) :-
findmax(Len,(append(_,[L|_],LL),length(L,Len)),MaxLen),
append(_,[LX|_],LL),
length(LX,MaxLen).
findmax(V,P,Max) :-
findall(V,P,L),
max(L,Max).
max([N],N) :- !.
max([N|R],Max) :-
max(R,Max2),
max3(N,Max2,Max).
max3(N,Max2,N) :- N > Max2,!.
max3(N,Max2,Max2).
【讨论】:
要获得最长列表的长度:
%sample: longest([[2,1,3],[7,5],[1,8,2,3,1],[2,7,1,4]],L,LEN).
longest([L], L, _) :-
!.
longest([H|T], H, _) :-
length(H, N),
longest(T, X, N),
length(X, M),
N > M,
!.
longest([_|T], X, LEN) :-
length(X, LEN),
longest(T, X, LEN),
!.
【讨论】: