Prolog从列表元素对到新列表更大

时间:2017-10-10 11:00:25

标签: list prolog

我想从列表的元素对中找到更大的值。 IE浏览器。 list = [5,7,4,5,6,8]这些对是[5,7],[7,4],[4,5]等。 现在我有这个小代码片段:

bigger([],X).
bigger([E1],[H|E1]).
bigger([E1,E2|T],[H|_]):-
   (E1>E2,bigger([E2|T],[H|E1]));
   (E1<E2,bigger([E2|T],[H|E2])).

解决方案应如下所示:

?- bigger([5,7,4,5,6,8],X).
X = [7,7,5,6,8,8]

编辑: 删除了删除/ 3行,因为它们错了。

我将了解代码的工作原理。

  1. 清空列表检查。
  2. 一个元素列表检查,将其添加到输出列表末尾([H | E1])
  3. 给定列表中的多个元素,输出列表

    3.1前两个元素检查(E1&gt; /&lt; E2)

    3.2没有E1(第一个元素)的新递归查询

    3.3无论哪个更大,输出列表的最后一个元素。

3 个答案:

答案 0 :(得分:2)

首先,我会向您展示我的问题解决方案(结果不应该是 /mnt/mysql/logs/ r, /mnt/mysql/logs/** rw, ?我会制作此版本。)

X = [7,7,5,6,8]

如果您希望最后一个元素出现在此列表中,而不仅仅是更改第二个gtr(X,Y,Y) :- Y>=X. gtr(X,_,X). bigger([],[]). bigger([_], []). bigger([X,Y|R], [Z|H]) :- bigger([Y|R],H), gtr(X,Y,Z),!. 函数。

答案 1 :(得分:2)

由于关系是描述列表,您可以选择使用DCG执行任务:

max_of(X,X,Y) :- X >= Y.   % X is maximum if X>=Y
max_of(Y,X,Y) :- Y > X.    % Y is maximum if Y>X

list_biggers(L,B) :-
   phrase(biggers(L),B).   % the DCG biggers//1 describes B based on L

biggers([]) -->            % if the list is empty
   [].                     % there's no element in the biggers list
biggers([X]) -->           % if the list contains just one element
   [X].                    % it is in the biggers list
biggers([X,Y|Xs]) -->      % if the list contains at least two elements
   {max_of(M,X,Y)},        % the maximum of them
   [M],                    % is in the biggers list
   biggers([Y|Xs]).        % the same holds for [Y|Xs]

这个定义坚持你对任务的阅读,也就是说,在单元素列表的情况下,唯一元素在更大元素的列表中:

?- list_biggers([5,7,4,5,6,8],B).
B = [7, 7, 5, 6, 8, 8] ;
false.

?- list_biggers([1],B).
B = [1] ;
false.

如果您更喜欢@Armatorix建议的读数,只需将第二个DCG规则更改为

biggers([_X]) -->
   [].

这样,上面的查询会产生以下结果:

?- list_biggers([5,7,4,5,6,8],B).
B = [7, 7, 5, 6, 8] ;
false.

?- list_biggers([1],B).
B = [] ;
false.

请注意,列表必须充分实例化。否则你会收到错误:

?- list_biggers([X,Y,Z],B).
ERROR: >=/2: Arguments are not sufficiently instantiated

如果列表只包含整数,则可以使用CLP(FD)解决此问题。添加一行以包含库并更改max_of / 2,如下所示:

:- use_module(library(clpfd)).

max_of(X,X,Y) :- X #>= Y.
max_of(Y,X,Y) :- Y #> X.

现在上面的查询提供了所有4个预期的解决方案:

?- list_biggers([X,Y,Z],B).
B = [X, Y, Z],
X#>=Y,
Y#>=Z ;
B = [X, Z, Z],
X#>=Y,
Y#=<Z+ -1 ;
B = [Y, Y, Z],
X#=<Y+ -1,
Y#>=Z ;
B = [Y, Z, Z],
X#=<Y+ -1,
Y#=<Z+ -1 ;
false.

答案 2 :(得分:1)

为了构建逻辑程序,需要思考逻辑。根据问题陈述,这里有三种可能性:

  • 我们有一个空列表,在这种情况下,结果也是一个空列表:

    bigger([],[]).
    
  • 如果我们有一个包含一个元素的列表,则问题不明确。我会说结果应该是一个空列表,但是你的例子似乎建议我们返回那个数字,因为我们有一个1元组,而1元组的最大值当然是元组中的单个元素:

    bigger([H],[H]).
    
  • 如果列表包含两个或更多元素[H1,H2|T],则H1H2是前两个元素。在这种情况下,我们在头部[H1,H2]构建一个虚拟元组并计算最大值,因此M is max(H1,H2)。我们将M添加到结果的递归列表中。该递归在列表[H2|T]上完成:我们从H1弹出的列表:

    bigger([H1,H2|T],[M|U]) :-
        M is max(H1,H2),
        bigger([H2|T],U).
    

或者将这些全部放在一起:

bigger([],[]).
bigger([H],[H]).
bigger([H1,H2|T],[M|U]) :-
    M is max(H1,H2),
    bigger(T,U).