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?
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
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
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.