foton
foton

Reputation: 11

number of zeros only in the even lists

What I need to add to count the number of zeros only in the even lists?

For example,

(count-zeroes '((1 1 1) (1 0 0) (1 1 1) (1 0 0))) 
 4

it is for one list.

(define count-zeroes
  (lambda (list)
    (cond ((null? list) 0)
          ((= 0 (car list)) (+ 1 (count-zeroes (cdr list))))
          (else (+ 0 (count-zeroes (cdr list))))
    )      
  )
)

Upvotes: 1

Views: 112

Answers (2)

WorBlux
WorBlux

Reputation: 1413

An interesting question. If you are operating on a lists of lists you need to add car-cdr recuresion.

(define (count-zeroes lst)  ;;don't override core function names with a variable
    (cond ((null? lst) 0) 
          ((pair? (car lst))
           (+ (count-zeroes (car lst))
              (count-zeroes (cdr lst))))
         ((= 0 (car lst)) 
          (+ 1 (count-zeroes (cdr lst))))
          (else (count-zeroes (cdr lst))))))

No as to only evens you are no longer counting zeros, so a new function name is in order. You could make up a higher order function like this.

(define (count-zeros-of selector lst)
  (count-zeroes (selector lst))) 

And make a general selector

(define (take-every-Xnth-at-y x y lst)
  (cond ((null? lst) '())
        ((= y 0) (cons (car lst)
                   (take-every x (- x 1) (cdr lst))))
        (else (take-every x (- y 1) (cdr lst))))) 

To put it all together

(define (count-zeroes-of-even lst)
    (count-zeroes-of 
       (lambda (lst) ;;to bad we can't do partial application
               (take-every-Xnth-at-y 2 1 lst))
       lst)     

Note each of these parts do their one thing and do it well.

Upvotes: 0

Joshua Taylor
Joshua Taylor

Reputation: 85853

(define count-zeroes
  (lambda (list)
    (cond ((null? list) 0)                                   ; a
          ((= 0 (car list)) (+ 1 (count-zeroes (cdr list)))) ; b
          (else (+ 0 (count-zeroes (cdr list)))))))          ; c

If list is initially a list of lists, then (null? list) in line a can be true (when you get to the end of the list), but the condition (= 0 (car list)) in the line b will never be true, since (car list) will always be another list, and 0 isn't a list.

A better way to break this down would probably be to first extract the even positioned sublists, then flatten them into a single list, and then count the zeros in those. That's not the most efficient way to do it (you'll create some intermediate storage), but you should probably implement something like that first, and then gradually optimize it afterward.

It's also worth noting that lists are typically indexed starting with position zero, so the second, fourth, etc., elements in the list are the ones with odd positions, not even positions. Here's the kind of abstraction that might help you in getting started with this kind of approach:

(define first car)
(define rest cdr)
(define list* cons)

(define (odds list)
  (if (null? list) '()
      (evens (cdr list))))

(define (evens list)
  (if (null? list) '()
      (list* (first list)
             (odds (rest list)))))

(define sample '((0 0 1) (0 1 0) (0 1 1) (1 0 0) (1 0 1) (1 1 0) (1 1 1)))

;; (display (odds sample))
;; => ((0 1 0) (1 0 0) (1 1 0))

Upvotes: 2

Related Questions