2
votes

How would I define a function in Dr. Racket which produces boolean true if all the numbers in a list are the same and false otherwise. This is my code so far:

(define (same-numbers? lst)
  (cond
    [(empty? (rest lst)) (first lst)]
    [else (equal? (first lst)(same-numbers? (rest lst)))]))

If I type in:

(same-numbers? (cons 5 (cons 5 (cons 5 empty))))

My desired output is true. However, instead, I get a false. How would I correct this?

3
You can just use (apply = lst)Atharva Shukla
(same-numbers? (list 5 5 5)) returns #f. (same-numbers? (list 5 5)) returns #t. (same-numbers? (list 5)) returns 5. (same-numbers? (list)) errors out. first thing to do about a recursive function definition is to take care that it always returns same type of result in all cases.Will Ness

3 Answers

2
votes

As the comments point out, assuming the list contains only numbers the simplest approach is to do (apply = lst). If you want to implement this from scratch with explicit recursion, I suggest a different approach: if the list has more than one element, take the first element as reference and compare all the others against it, like this:

(define (same-numbers? lst)
  (if (or (empty? lst) (empty? (rest lst))) ; trivial cases
      #t
      (let loop ((val (first lst)) ; take first element as reference
                 (lst (rest lst))) ; loop over the other elements
        (or (empty? lst)           ; base case: we're finished
            (and (equal? (first lst) val)   ; base case: stop if elements are different
                 (loop val (rest lst))))))) ; recursive case: keep iterating

It works for my test cases:

(same-numbers? '())
=> #t
(same-numbers? '(5))
=> #t
(same-numbers? '(5 5))
=> #t
(same-numbers? '(5 5 5))
=> #t

(same-numbers? '(5 1))
=> #f
(same-numbers? '(1 5))
=> #f
(same-numbers? '(1 5 5))
=> #f
(same-numbers? '(5 5 1))
=> #f
2
votes

I'll start with your code so far, and find the problems with it:

(define (same-numbers? lst)
  (cond
    [(empty? (rest lst)) (first lst)]
    [else (equal? (first lst)(same-numbers? (rest lst)))]))

The first problem I see is with the base case: if lst is a list of numbers then (first lst) will be a number, not a boolean like you wanted.

;; same-numbers? : [Listof Number] -> Boolean

To fix this, the base case should return #true:

(define (same-numbers? lst)
  (cond
    [(empty? (rest lst)) #true]
    [else (equal? (first lst) (same-numbers? (rest lst)))]))

The next problem I see is with the recursive case: since same-numbers? returns a boolean, you shouldn't use equal? as if you're expecting a number. Instead use equal? between the first and the second:

(define (same-numbers? lst)
  (cond
    [(empty? (rest lst)) #true]
    [else ... (equal? (first lst) (second lst)) ... (same-numbers? (rest lst)) ...]))

Now the ...s around that need to be filled with stuff that combines the information in "first two equal" and "rest same-numbers". They're all equal when the first two are equal AND the rest are the same, so fill in the ...s with and to combine them:

(define (same-numbers? lst)
  (cond
    [(empty? (rest lst)) #true]
    [else (and (equal? (first lst) (second lst)) (same-numbers? (rest lst)))]))

If I type in:

> (same-numbers? (cons 5 (cons 5 (cons 5 empty))))
#true

There's still one problem left: the empty list. So just add another cond case for it:

;; same-numbers? : [Listof Number] -> Boolean
(define (same-numbers? lst)
  (cond
    [(empty? lst)        #true]
    [(empty? (rest lst)) #true]
    [else (and (equal? (first lst) (second lst)) (same-numbers? (rest lst)))]))

Using it:

> (same-numbers? empty)
#true
> (same-numbers? (cons 5 empty))
#true
> (same-numbers? (cons 5 (cons 5 (cons 5 empty))))
#true
> (same-numbers? (cons 5 (cons 5 (cons 6 empty))))
#false
1
votes

Just like Atharva Shukla's comment (apply = lst) is good.

But (apply = '()) will show error.

#lang Racket
(define lon (list 1/2 1/2 1/2 1/3))
(define lon2 (list 1/2 1/2 1/2 0.5))

(define (same-n? lon)
  (andmap (lambda (n) (= (first lon) n)) lon))

;;; TEST

(same-n? lon) ; #f
(same-n? lon2) ; #t
(same-n? '()) ; #t