如何获得列表方案和序言的第一个,中间和最后一个元素?

时间:2015-05-07 21:37:46

标签: list prolog scheme

我正在尝试在Scheme和Prolog中编写一个函数来返回列表的第一个,中间和最后一个项目。例如,find([4,5,8,7,9],L), L = [4,8,9]

我为Scheme语言提出了这段代码,但我是Prolog的新手并且不太了解,所以如何在Prolog中获得相同的结果?

(define (frst L)
   (car L))

(define (last L)
   (if (null? (cdr L))
       (car L)
       (last (cdr L))))

(define (nth L x)
   (if (= x 1)
       (car L)
       (nth (cdr L) (- x 1))))

(define (firstMidLast L)
   (list (frst L)
         (nth L (ceiling (/ (length L) 2)))
         (last L)))

2 个答案:

答案 0 :(得分:3)

这是另一种方法!

  • "技巧"是以两种不同的速度走下相同的列表。
  • 第一个参数索引使目标list_first_mid_last(+,?,?,?)保持确定性。

我们这样定义list_first_mid_last/4

list_first_mid_last([E|Es],E,M,L) :-
    ahead_of_mid_last([E|Es],[E|Es],M,L).

ahead_of_mid_last([],[M|_],M,M).
ahead_of_mid_last([F|Fs],Es,M,L) :-
   more_ahead_of_mid_last(Fs,F,Es,M,L).

more_ahead_of_mid_last([],L,[E|_],E,L).
more_ahead_of_mid_last([F|Fs],_,Es,E,L) :-
   evenmore_ahead_of_mid_last(Fs,F,Es,E,L).

evenmore_ahead_of_mid_last([],L,[E|_],E,L).
evenmore_ahead_of_mid_last([F|Fs],_,[_|Es],M,L) :-
    more_ahead_of_mid_last(Fs,F,Es,M,L).

让我们运行一些查询并将Prolog 1 和Scheme 2 结果并排放置!

%  Prolog                                     % ; Scheme
?- list_first_mid_last([1],F,M,L).            % > (firstMidLast `(1))
F = M, M = L, L = 1.                          % (1 1 1)
                                              %
?- list_first_mid_last([1,2],F,M,L).          % > (firstMidLast `(1 2))
F = M, M = 1, L = 2.                          % (1 1 2)
                                              %
?- list_first_mid_last([1,2,3],F,M,L).        % > (firstMidLast `(1 2 3))
F = 1, M = 2, L = 3.                          % (1 2 3)
                                              %
?- list_first_mid_last([1,2,3,4],F,M,L).      % > (firstMidLast `(1 2 3 4))
F = 1, M = 2, L = 4.                          % (1 2 4)
                                              %
?- list_first_mid_last([1,2,3,4,5],F,M,L).    % > (firstMidLast `(1 2 3 4 5))
F = 1, M = 3, L = 5.                          % (1 3 5)
                                              %
?- list_first_mid_last([1,2,3,4,5,6],F,M,L).  % > (firstMidLast `(1 2 3 4 5 6))
F = 1, M = 3, L = 6.                          % (1 3 6)
                                              %
?- list_first_mid_last([1,2,3,4,5,6,7],F,M,L).% > (firstMidLast `(1 2 3 4 5 6 7))
F = 1, M = 4, L = 7.                          % (1 4 7)

脚注1:使用版本7.3.11(64位)。
脚注2:使用解释器SCM版本5e5(64位)。

答案 1 :(得分:1)

假设如果列表中包含偶数项目,您可以选择其中一项(在本例中为第一项),此过程应该有效:

根据用户'重复'的评论进行编辑(我不熟悉计划)

find([First|List], [First, Middle, Last]):-
  append(_, [Last], [First|List]),
  length(List, Length),
  NLength is Length >> 1,
  nth0(NLength, [First|List], Middle).

子句的头部实例化列表的第一项,然后append/3取最后一项,length/2计算列表的大小-1,>>/2将除以该大小按2,nth0/3将获得中间项目。