打印列表的相邻副本(方案)

时间:2015-12-10 17:17:48

标签: scheme lisp

我尝试创建一个返回列表相邻副本的函数,例如(dups'(1 2 1 1 1 4 4)应该返回列表(1 4)。

这是我到目前为止提出的代码:

(define (dups lst)
    (if (equal? (car lst)(car(cdr lst)))
        (cons(cdr lst) '())
        (dups(cdr lst))))

此函数不会返回所有相邻的重复项,它只返回第一个相邻的重复项! 如何修复它以便返回列表的所有相邻副本?

谢谢。

3 个答案:

答案 0 :(得分:3)

一旦您的代码找到重复内容,它就会停止处理列表的其余部分:当if测试为真时,它会产生(cons (cdr lst) '())。无论是否发现重复,它仍应调用dups来处理列表的其余部分。

另外:如果您的列表没有重复项,则会遇到麻烦。

这是一个比其他人发布的更简单的解决方案:

(define (dups lst)
    (if (< (length lst) 2)
        ; No room for duplicates
        '()
        ; Check for duplicate at start
        (if (equal? (car lst) (cadr lst))
            ; Starts w/ a duplicate
            (if (or (null? (cddr lst)) ; end of list
                    (not (equal? (car lst) (caddr lst)))) ; non-matching symbol next
                ; End of run of duplicates; add to front of what we find next
                (cons (car lst) (dups (cdr lst)))
                ; Othersise keep looking
                (dups (cdr lst)))
            ; No duplicate at start; keep looking
            (dups (cdr lst)))))

答案 1 :(得分:3)

基本上,这归结为仅保留与前一个元素相同但与下一个元素不同的元素。

这是使用名为let的示例实现。

(define (adj-dups lst)
      (let loop ((lst (reverse (cons (gensym) lst)))
                 (e-2 (gensym))
                 (e-1 (gensym))
                 (acc '()))
        (if (null? lst) 
            acc
            (let ((e-0 (car lst)))
              (loop (cdr lst)
                    e-1
                    e-0
                    (if (and (eqv? e-2 e-1) (not (eqv? e-1 e-0)))
                        (cons e-1 acc)
                        acc))))))

(gensym)在这里派上用场,因为它是一种方便的方法,可以使用与其他所有内容不同的内容初始化工作变量,并使用需要的虚拟元素填充初始列表添加,以便我们不会错过最后一个元素。 测试:

> (adj-dups '())
'()
> (adj-dups '(1 1 4 4 1 1))
'(1 4 1)
> (adj-dups '(1 1 1 1 1))
'(1)
> (adj-dups '(1 2 1 1 1 4 4))
'(1 4)
> (adj-dups '(2 3 3 4 4 4 5))
'(3 4)

答案 2 :(得分:1)

我能想到解决这个问题的最直接的方法是使用一个内部过程,一个额外的变量来跟踪前一个元素是什么,一个布尔值来跟踪元素是否重复。然后,您可以在辅助函数和main函数之间执行相互递归,以一次构建一个重复元素的答案。

(define (dups lst)
   (define (dups-helper x repeat? L)
      (cond ((null? L)
             (if repeat? 
                 (list x)
                 '()))
            ((equal? x (car L))
             (dups-helper x #t (cdr L)))
            (else 
             (if repeat?
                 (cons x (dups L))
                 (dups L)))))
  (if (null? lst)
      '()
      (dups-helper (car lst) #f (cdr lst))))

(dups (list 1 1 4 4 5 6 3 3 1))
 ;Value 43: (1 4 3)