tScheme新手问题:
我需要确定列表是否包含使用递归的偶数或奇数量的原子。我知道简单的方法是获取列表长度并确定它是偶数还是奇数,但我希望看到它是使用递归完成的。
(oddatom
(LIST 'x 'y 'v 'd 'r 'h 'y))
应该返回#t
,而
(oddatom
'((n m) (f p) l (u k p)))
应该返回#f
欣赏帮助。
答案 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)))))))
表示:
car
或cdr
中只有一个可能是奇数(独占或)。测试用例(在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
>