Print adjacent duplicates of a list (scheme)

不问归期 提交于 2019-12-12 15:31:00

问题


I'm trying to create a function that returns the adjacent duplicates of a list, for example (dups '(1 2 1 1 1 4 4) should return the list (1 4).

This is the code I came up with so far:

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

This function doesn't return all the adjacent duplicates, it only returns the first adjacent duplicates! How can I fix it so that it returns all the adjacent duplicates of a list?

Thank you.


回答1:


Once your code finds a duplicate, it stops processing the rest of the list: when the if test is true, it yields (cons (cdr lst) '()). Whether or not it finds a duplicate, it should still be calling dups to process the rest of the list.

Also: if your list has no duplicates, it it going to run into trouble.

Here's a simpler solution than the others posted:

(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)))))



回答2:


Basically this boils down to only keeping the elements which are the same as the previous one, but different from the next.

Here's an example implementation using a named 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) comes in handy here because it's a convenient way to initialise the working variables with something that's different from everything else, and filling up the initial list with a dummy element that needs to be added so that we don't miss the last element. Testing:

> (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)



回答3:


The most straightforward way I can think of to tackle this is with an internal procedure with an extra variable to keep track what the prior element was and a boolean to track if the element was repeated. You can then do a mutual recurstion between the helper and main function to build the answer one duplicate element at a time.

(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)


来源:https://stackoverflow.com/questions/34207933/print-adjacent-duplicates-of-a-list-scheme

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!