找到Prolog中最长的列表?

时间:2015-11-16 16:12:24

标签: prolog

我需要写一个谓词longestList / 2,这样如果L2是最长的,则满足longestList(L1,L2) 列表列表L1中的嵌套列表。

?- longestList([[1],[1,2],[1,2,3],[1,2,3,4]],LI).
LI = [[1, 2, 3, 4]] ;
No
?- longestList([[a,b,c],[d,e],[f,g,h]],LI).
LI = [[f, g, h],[a,b,c]];
No

有人可以用直觉帮我解决问题吗?

3 个答案:

答案 0 :(得分:3)

这是一个基本的递归方法的大纲。不像@CapelliC给出的答案那么清晰,但是按照简单的顺序。

想法是遍历列表并跟踪到目前为止看到的最长列表,以及它的长度。然后,如果条件指示,则递归地逐步遍历列表并更新这些参数以进行递归。这是用于执行递归“max list element”谓词的技术的细微阐述。为此,您需要设置一个调用以包含更多参数(当前最长列表及其长度)。

longestList([], []).
longestList([L|Ls], LongestList) :-
    length(L, Length),
    % Start with the first element (L) being my best choice so far
    longestList(Ls, L, Length, LongestList).

这是带有新参数的扩展谓词。

longestList([L|Ls], LongestListSoFar, GreatestLengthSoFar, LongestList) :-
    % Here, you need to examine L and determine if it should supersede
    %  the longest list so far and its length. You need to keep in mind that
    %  if the length of L is the same as the max length so far, then I
    %  may choose to keep the LongestListSoFar, or choose L. Both are
    %  valid solutions for this call. This is a good place to use the `;`
    %  operator, and to be cautious about parenthesizing expressions since
    %  the comma has higher precedence than the semi-colon.
    %  Also, you'll need to make a recursive call to longestList(Ls, ??, ??, LongestList).
    %  The arguments to the recursion will depend upon which way the decision flow goes.
    %
    % After all that to-do, don't let it scare you: it's about 5 lines of code :)
    %
longestList([], LongestListSoFar, ??, ??).
    % Fill in the ??. What should they be at list's end ([])?
    %   Do I even care now what the 3rd argument is?

希望这足以让你有所思考取得进步。或者,使用@ CapelliC的解决方案并编写member_length/3谓词。 :)请注意,正如在他的解决方案中,如果有多个,上述解决方案将在回溯时生成每个最大列表。因此,如果您想在一个列表中获取所有解决方案,则可以使用findall/3

答案 1 :(得分:2)

member / 2允许你从列表中查看一个元素(你的案例列表):所以,如果你有一个member_length / 3谓词,你可以编码

longestList(Lists, Longest) :-
  member_length(Lists, Longest, N),
  \+ ( member_length(Lists, _Another, M), M > N ).

然后找到所有最长的,你可以使用findall / 3 ...

答案 2 :(得分:1)

以下使用if else的代码似乎部分工作。它必须以0长度调用,因此从这里无法获得长度。

longest_list([H|T], LongList, LongLen):-
    length(H, Len),
    (Len > LongLen -> 
        longest_list(T, [H], Len); 
        longest_list(T, LongList, LongLen)).

longest_list([],Finallist,_):-writeln(Finallist).

?- longest_list([[1,2,3], [3,4], [4,5,6,7,8], [5,3,4]], Longestlist, 0).
[[4,5,6,7,8]]
true.

然而,变量本身并未到来:

?- writeln(Longestlist).
_G1955
true.

它可能会提供一些想法。