Reputation: 169
I'm trying make an iterative procedure which compare every odd and every even elements in a list. Every odd number should be odd and every even should be even. First number must be odd. Output should be like this:
(odd-even-args? 1 2 3 4 5) --> #t
(odd-even-args? 1 2 4 4 5) --> #f
(odd-even-args? 1 0 1) --> #t
I tried to compare two element with this: (and (odd? (car lst)) (even? (cadr lst))
, but I don't know how to continue with (cddr lst)
.
Upvotes: 4
Views: 2032
Reputation: 598
As an exercise, I wrote a version using SRFI-1 and fold:
(define (odd-even-args? . xs)
(first
(fold
(lambda (x data)
(let ((result (first data))
(count (second data)))
(list
(and
((if
(odd? count)
odd?
even?)
x)
result)
(+ 1 count))))
'(#t 1)
xs)))
Upvotes: 0
Reputation: 1413
Why not design the general case as a higher order function and implement odd-even? as a special case? that way you can also implement even-odd?, or square?-tan?, or prime?-carmicheal? quite easily.
(define (predx?-predy? predx predy)
(lambda L
(let loop ((lst L) (pred?1 predx) (pred?2 predy))
(if (null? lst)
#t
(and (pred?1 (car lst)) (loop (cdr lst) pred?2 pred?1))))))
;;flip preds each recursion
(define odd-even? (predx?-predy? odd? even?))
(define even-odd? (predx?-predy? even? odd?))
(define square-tan (predx?-predy? square? tan?))
(define prime?-Carmichael? (predx?-predy? prime? (lambda (x) (and (not (prime? x)) (fermat-prime? x)))))
Upvotes: 0
Reputation: 4578
(define (range start end)
(if (>= start end)
nil
(cons start (range (+ start 1) end)))
(define (odd-even-args? . args)
(apply and
(map (lambda (value index)
(eqv? (even? index)
(even? value)))
args
(range 1 (+ 1 (length args))))))
Upvotes: 0
Reputation: 236004
Here's one possibility: traverse all the list, asking if each element satisfies the appropriate predicate (either even?
or odd?
) and alternate between the predicates:
(define (odd-even-args? . lst)
(let loop ((lst lst)
(is-odd? #t))
(if (null? lst)
#t
(and ((if is-odd? odd? even?) (car lst))
(loop (cdr lst) (not is-odd?))))))
The answer above uses an and
with the recursive call in a tail position, so it's iterative - and it's similar to the way you were thinking about the solution. Here's another solution which shows more explicitly that this is indeed an iterative process:
(define (odd-even-args? . lst)
(let loop ((lst lst)
(is-odd? #t))
(cond ((null? lst) #t)
(((if is-odd? even? odd?) (car lst)) #f)
(else (loop (cdr lst) (not is-odd?))))))
And yet another solution, using boolean connectors instead of conditional expressions:
(define (odd-even-args? . lst)
(let loop ((lst lst)
(is-odd? #t))
(or (null? lst)
(and ((if is-odd? odd? even?) (car lst))
(loop (cdr lst) (not is-odd?))))))
Upvotes: 5
Reputation: 5675
Just another variant ( probably not good one .. )
(define (odd-even-args? . args)
(define (iter lst)
(cond ((null? lst) #t)
((null? (cdr lst)) (odd? (car lst)))
((and (odd? (car lst)) (even? (cadr lst))) (iter (cddr lst)))
(else #f)))
(iter args))
Upvotes: 2