Scheme中列表的非递减列表?

问题描述 投票:-3回答:2

[我们需要一个名为nondecreaselist的Scheme函数,该函数接收一个数字列表并输出一个列表列表,这些列表总体上具有相同的数字且顺序相同,但分为不递减的列表。

例如,如果我们输入了(1 2 3 4 1 2 3 4 1 1 1 2 1 1 0 4 3 2 1),则输出应为:

((1 2 3 4) (1 2 3 4) (1 1 1 2) (1 1) (0 4) (3) (2) (1))

您将如何实施?我知道我们必须使用递归。到目前为止我的尝试:

(define (nondecreaselist s) 
  (cond ((null? s) '())
        ((cons (cons (car s)
                     ((if (and (not (null? (cadr s)))
                               (not (> (car s) (cadr s))))
                          ((cadr s))
                          ('()))))
               (nondecreaselist (cdr s))))))

但是,这给了我错误:

(int)不可调用:

list sorting recursion scheme partitioning
2个回答
1
投票
(define decrease-list
  (lambda (l)
    ((lambda (s) (s s l cons))
     (lambda (s l col)
       ;; limitcase1: ()
       (if (null? l)
           (col '() '())
           ;; limitcase2: (a1)
           (if (null? (cdr l))
               (col l '())
               (let ((a1 (car l)) (a2 (cadr l)))
                 ;; limitcase3: (a1 a2)
                 (if (null? (cddr l))
                     (if (>= a2 a1)
                         (col l '())
                         (col (list a1) (list (cdr l))))
                     ;; most usual case: (a1 a2 ...)
                     (s s (cdr l)
                        (lambda (g l*)
                          (if (>= a2 a1)
                              (col (cons a1 g) l*)
                              (col (list a1) (cons g l*)))))))))))))

1 ]=> (decrease-list '(1 2 3 4 1 2 3 4 1 1 1 2 1 1 0 4 3 2 1))
;Value: ((1 2 3 4) (1 2 3 4) (1 1 1 2) (1 1) (0 4) (3) (2) (1))

我没有对此发表评论,如果您有任何问题可以问,但是我认为您也可以研究我自己为您编写的代码。

还请注意,可以不加考虑循环极限情况()(a1),只检查一次这些情况:

(define decrease-list
  (lambda (l)
    ;; limitcase1: ()
    (if (null? l)
        '()
        ;; limitcase2: (a1)
        (if (null? (cdr l))
            (list l)
            ((lambda (s) (s s l cons))
             (lambda (s l col)
               (let ((a1 (car l)) (a2 (cadr l)))
                 ;; limitcase3: (a1 a2)
                 (if (null? (cddr l))
                     (if (>= a2 a1)
                         (col l '())
                         (col (list a1) (list (cdr l))))
                     ;; most usual case: (a1 a2 ...)
                     (s s (cdr l)
                        (lambda (g l*)
                          (if (>= a2 a1)
                              (col (cons a1 g) l*)
                              (col (list a1) (cons g l*)))))))))))))

1
投票

发布的代码存在一些问题。第二个cond子句中没有测试表达式; if及其子句周围有太多括号。也许最重要的问题是代码正在尝试构建一个非递减列表,该列表将被cons转换为(nondecreaselist (cdr s))的结果,但是当非递减序列的长度超过一个数字时,它将开始再次回到(cdr s),在输入列表中又过早了。

整理操作码

可以清除逻辑。输入为空列表时,OP代码已经在返回空列表。代替测试(null? (cadr s))(当(cdr s)'()时,cadr无法在s上工作),可以在代码尝试输入(null? (cdr s))之前测试(cadr s)。但是最好是改变这种逻辑。当输入列表包含一个元素时,仅返回包含输入列表的列表:((null? (cdr s)) (list s))

代替(and (not (> ;...,可以通过测试>并执行适当的操作来使逻辑更清晰。在这种情况下,当(> (car s) (cadr s))应该启动一个新的子列表,并且将cons放入到从nondecreaselist返回的结果的子列表中。

否则,应将(car s)添加到从nondecreaselist返回的结果中的第一个子列表中。为此,我们需要通过以下方式构造返回列表:conss放入第一个子列表,然后cons将新的子列表放回子列表的列表cdr,这是从中返回的结果nondecreaselist

这里是一些修改后的代码:

(define (nondecreaselist s) 
  (cond ((null? s) '())
        ((null? (cdr s)) (list s))
        ((> (car s) (cadr s))
         (cons (list (car s))
               (nondecreaselist (cdr s))))
        (else
         (let ((next (nondecreaselist (cdr s))))
           (cons (cons (car s)
                       (car next))
                 (cdr next))))))

使用助手功能

另一种方法是定义一个辅助函数,该函数以输入列表和累积列表为参数,返回列表列表。 helper函数将从输入列表的前面获取数字,然后将其添加到累加器中,创建一个非递减列表,或者将cons累加的非递减列表转换为对其余列表进行运算的结果输入。

如果辅助函数lst的输入ndl-helper为空,则应返回包含累积的非递减列表sublst的列表。请注意,sublst由于其构造方式而需要在返回之前反转,如下所述。

如果累加器sublst为空,或者输入列表中的下一个数字大于或等于sublst中的最大数字,则应将下一个数字简单地添加到[ C0]。通过将数字sublst放在cons的前面,只需检查sublstcar,因为它始终是sublst中的最大值(或等于最大值)。但是,由于sublst的顺序相反,因此需要先将其反转,然后再将其添加到不断增长的列表中。

否则,sublst不为空,并且lst不为空,并且输入列表中的下一个数字小于sublst中的最大数字。因此,需要启动一个新的子列表,因此通过使用空累加器sublst在其余sublst上调用helper函数,可以将旧的cons反向并lst到剩余计算的结果上:

sublst

两个功能均起作用:

(define (nondecreaselist-2 lst)
  (define (ndl-helper lst sublst)
    (cond ((null? lst) (list (reverse sublst)))
          ((or (null? sublst)
               (>= (car lst) (car sublst)))
           (ndl-helper (cdr lst) (cons (car lst) sublst)))
          (else
           (cons (reverse sublst) (ndl-helper lst '())))))
  (ndl-helper lst '()))
© www.soinside.com 2019 - 2024. All rights reserved.