Maryam
Maryam

Reputation: 11

Scheme - function to count occurrences of atom in argument

I'm new to scheme and trying to learn functions. I want to create a function where I can count all occurrences of the atom "a" in an argument. This is what I have written so far. I'm not sure what to write in the third condition. Please help out.

(define (count-a arg)
   (COND
     ((null? arg) 0)
     ((eq? arg 'a) 1)
     ((list? arg) ( ___ + ( ___ count-a arg)))
     (else 0)
     
))

This is the output i want:

(count-a 'a) 1

(count-a 'aa) 0

(count-a '(a)) 1

(count-a '(ab c) 0

(count-a '(a (b c) (c (d a) a) (((a b))))) 5

Upvotes: 1

Views: 145

Answers (2)

Thomas Blankenhorn
Thomas Blankenhorn

Reputation: 256

Welcome to Stack Overflow!

Solution:

(define (count-a  arg)
  (cond ((null? arg) 0)
        ((not (pair? arg)) 
          (if (equal? arg 'a)
              1
              0))
        ;; At this point we know arg is a pair, and we recurse.
        (else (+ (count-a (car arg)) (count-a (cdr arg))))))

Test:

Here are the tests you specified, compressed into a single line.

;; Chibi-Scheme REPL - other implementations might look different.
> (map  count-a '(a aa (a) (ab c) (a (b c) (c (d a) a) (((a b))))))
(1 0 1 0 4)

You didn't say what you want to happen if arg is a dotted pair. But let's check it out just for fun.

> (map count-a '((ab . '()) (ab . a) (a . a)))
(0 1 2)

So when I run your last test on my code, it yields 4 where you expected 5. I maintain that my code is correct and your test specification is incorrect, as there are only four instances of 'a in the argument of count-a.

Discussion:

You specified in your headline that the thing the count-a function will be counting is an atom. So you have to check whether arg is an atom or not. Since Scheme doesn't have an atom? function, I'll assume that an atom is anything that's not '() and not a pair. (This is consistent with the atom function of Common Lisp, as well as other Lisp dialects.)

Since your code already deals with arg being '(), we only have to deal with arg being, or not being a pair.

If arg is not a pair and (equal? arg 'a), then (count-a arg) equals 1. Else, it equals 0.

If arg is a pair, we can recurse into car arg) and (cdr arg), however deeply nested arg may be, and increase our count whenever we find an atom that equals a.

Hope that helps.

Upvotes: 1

Sylwester
Sylwester

Reputation: 48745

(___ + ( ___ count-a arg)) doesn't seem right to me. Remember Scheme is a prefix language. It's (+ 1 2 3) instead of 1 + 2 + 3.

In the third one you have two lists parts. eg. '(a a) so you need to call count-a on the car and on the cdr of the list and add the results together. eg. (count-a '(a a)) should give the same result as (+ (count-a 'a) (count-a '(a))

Good luck

Upvotes: 2

Related Questions