如何确定列表是否具有偶数或奇数个原子

时间:2014-04-02 19:23:44

标签: scheme

tScheme新手问题:

我需要确定列表是否包含使用递归的偶数或奇数量的原子。我知道简单的方法是获取列表长度并确定它是偶数还是奇数,但我希望看到它是使用递归完成的。

(oddatom 
  (LIST 'x 'y 'v 'd 'r 'h 'y))

应该返回#t,而

(oddatom 
  '((n m) (f p) l (u k p)))

应该返回#f

欣赏帮助。

5 个答案:

答案 0 :(得分:1)

这是我的解决方案版本:

(define (oddatom? lst)
  (let recur ((odd #f)
              (x lst))
    (cond ((null? x) odd)
          ((pair? x) (recur (recur odd (car x)) (cdr x)))
          (else (not odd)))))

答案 1 :(得分:1)

我喜欢Chris Jester-Young's answer,但我认为值得提供一个尾递归版本来维护自己的堆栈。请注意,这是将非尾递归转换为尾递归的练习,这对于Scheme中的某些算法来说是一种非常有用的技术。但是,在这种情况下,它可能并不那么重要,Chris Jester-Young回答的代码感觉更自然。因此,将此作为一项练习,不一定是一项重大改进。

这里的想法是内部函数odd?采用事物列表,并且指示到目前为止是否已经看到奇数个原子(除空列表之外)的值。

(define (oddatom? thing)
  (let odd? ((things (list thing))
             (result #f))
    (cond
      ;; We're out of things to see.  Did we see an odd number of things?
      ((null? things)
       result)
      ;; Our list of things has the form ((x . y) …), so we recurse on 
      ;; (x y …), with the *same* value for result, since we haven't 
      ;; "seen" x or y yet, we've just "unwrapped" them.
      ((pair? (car things))
       (odd? (cons (caar things) (cons (cdar things) (cdr things))) result))
      ;; Our list of things has the form (() …), so we recurse on 
      ;; (…), with the *same* value for result, since we haven't "seen" any
      ;; additional atoms.
      ((null? (car things))
       (odd? (cdr things) result))
      ;; Our list of things has the form (<atom> …), so we recurse on (…), 
      ;; but with a flipped value for result, since we've seen one more atom.
      (else
       (odd? (cdr things) (not result))))))

最后两个案例可以合并,使第二个递归参数基于(null? (car things))的值为:

(define (oddatom? thing)
  (let odd? ((things (list thing))
             (result #f))
    (cond
      ((null? things)
       result)
      ((pair? (car things))
       (odd? (cons (caar things) (cons (cdar things) (cdr things))) result))
      (else
       (odd? (cdr things) (if (null? (car things))
                              result
                              (not result)))))))

答案 2 :(得分:0)

我会这样做:

(define (oddatom lst)
  (cond
    ((null? lst)       #f)
    ((not (pair? lst)) #t)
    (else (not (eq? (oddatom (car lst)) (oddatom (cdr lst)))))))

表示:

  1. 空列表不是奇数(#f)
  2. 原子是奇数(#t)
  3. 否则,列表的carcdr中只有一个可能是奇数(独占或)。
  4. 测试用例(在Racket中),包括不正确的列表:

    (require rackunit)
    (check-equal? (oddatom (list 'x 'y 'v 'd 'r 'h 'y)) #t)
    (check-equal? (oddatom '((n m) (f p) l (u k p))) #f)
    (check-equal? (oddatom '(a (b) c)) #t)
    (check-equal? (oddatom (cons 1 2)) #f)
    (check-equal? (oddatom 1) #t)
    (check-equal? (oddatom '(1 (2 . 3))) #t)
    

答案 3 :(得分:0)

这是一个:

(define (odd-atom? obj)
  (and (not (null? obj))
       (or (not (pair? obj))
           (let ((this? (odd-atom? (car obj)))
                 (rest? (odd-atom? (cdr obj))))
             (or (and (not this?) rest?)
                 (and (not rest?) this?))))))

或者,从@uselpa学习简化'或者这个?休息?'上面的逻辑,另一个:

(define (odd-atom? obj)
  (and (not (null? obj))
       (or (not (pair? obj))
           (not (eq? (odd-atom? (car obj))
                     (odd-atom? (cdr obj)))))))

答案 4 :(得分:0)

如果'()是一个原子(就像在CommonLisp中,'()也是T),那么它应该是(odd-atom? '(() () ())) #t

(define (odd-atom? obj)
  (and (not (null? obj))
       (or (not (pair? obj))
           (let ((this? (or (null?     (car obj)) 
                            (odd-atom? (car obj))))
                 (rest? (odd-atom? (cdr obj))))
             (not (eq? this? rest?))))))
> (odd-atom? '())
#f
> (odd-atom? '(()))
#t
> (odd-atom? '(() () ()))
#t
> (odd-atom? '(() ()))
#f
> (odd-atom? '(() (a)))
#f
> (odd-atom? '(() (a b)))
#t
> (odd-atom? '((a) (a b)))
#t
> (odd-atom? '((a b) (a b)))
#f
>