>: expects a real, given (void) - racket

I am currently struggling with creating a list that finds if all the numbers within the list are equal to each other:
(define (list-all-equal lon) (cond [(empty? lon) lon]
[(empty? (rest lon)) (first lon)]
[(empty? (rest (rest lon))) (first lon)]
[(equal? (first lon) (list-all-equal(rest lon))) (write #true)]
[(> (first lon) (list-all-equal(rest lon))) (write #false)]
[(< (first lon) (list-all-equal(rest lon))) (write #false)]
[else (list-all-equal (rest lon))]))
However, I keep on receiving the error: >: expects a real, given void. is there a way to solve the error?

write does not return a value, so when you compare to the recursive result you're going to end up comparing to "nothing".
Also, your function should return #true or #false, not list elements, and comparing list elements to the results of recursing does not make much sense.
I think you started writing code before solving the problem.
A helpful way to start is with listing the possibilities.
All elements of an empty list are equal
All elements of a singleton list are equal
If the list has at least two elements, and the first element is equal to the second element, all the elements are equal if and only if all elements in its tail are equal
Otherwise, there is at least one unequal element
Translated:
(define (list-all-equal lon)
(cond [(empty? lon) #true]
[(empty? (rest lon)) #true]
[(equal? (first lon) (second lon)) (list-all-equal (rest lon))]
[else #false]))

The problem is that you're calling write as part of the recursion, and write "returns" void, which will lead to something like this:
(> some-number (void))
Never use write to return a value from your procedures! We want to return the results, not to display them on the console. And for this case you have to implement your procedure in such a way that, if it finds a different number, it stops comparing - the result is false and we shouldn't continue. A good strategy would be to pass along the first element and compare the rest against it:
(define (list-all-equal lst)
(if (empty? lst)
#t
(list-all-equal-helper (first lst) (rest lst))))
(define (list-all-equal-helper ele lst)
(cond ((empty? lst) #t)
((not (= (first lst) ele)) #f)
(else (list-all-equal-helper ele (rest lst)))))
Or, we could use apply :)
(define (list-all-equal lst)
(apply = lst))
Either way, it works as expected:
(list-all-equal '(1 2 3))
=> #f
(list-all-equal '(1 1 1))
=> #t

Related

How can I use more than "return" statement in the following piece of code?

In my else condition I have two statements to execute. The first one ought to append my calculation to my return-list and the second one calls my recursive procedure again.
The problem is that my append procedure is being ignored so I am just returning an empty list.
(define (calcit x lst)
(cond ((= x 0)
retlst)
(else (append (list (floor (/ x (first lst)))) retlst)
(calcit (modulo x (first lst)) (rest lst)))))
You need to do something with the data you are creating. You probably want to have the first element consed on the result of the list you get from the recursion:
(define (calcit x lst)
(if (= x 0)
'() ;; base case
(cons (floor (/ x (first lst)))
(calcit (modulo x (first lst)) (rest lst)))))
When creating lists in Scheme with recursion try to avoid append. Using append is an anti pattern. Learn how Scheme lists work and train to know it intimately. eg '((2 3) (4 5)) if I ask you how to get 5 from that you should think d a d a and answer cadadr almost right away.

Calculating the number of matches for every sublist separately

Here is my big list with sublists:
(define family
(list
(list 'Daddy 't-shirt 'raincoat 'sunglasses 'pants 'coat 'sneakers)
(list 'Mamma 'high-heels 'dress 'pants 'sunglasses 'scarf)
(list 'son 'pants 'sunglasses 'sneakers 't-shirt 'jacket)
(list 'daughter 'bikini 'Leggings 'sneakers 'blouse 'top)))
And i want to compare family with this simple list:
(list 'sneakers 'dress 'pants 'sunglasses 'scarf)
each matching should give 1 point and i want that the point to be calculated separately for each sublist.
Here is the code:
;checking if an element exists in a list
(define occurs?
(lambda (element lst)
(cond
[(and (null? element) (null? lst))]
[(null? lst) #f]
[(pair? lst)
(if
(occurs? element (car lst)) #t
(occurs? element (cdr lst)))]
[else (eqv? element lst)])))
;--------------------------------------
; a list of just names are created.
(define (name-list lst)
(list (map car lst)))
; Each sublist has a name (car of the sublist). The name-list turn to point-list for each sublist. All of my code except the code below is functioning as i want. The problem lies within point-list code.
(define (point lst db)
(let ((no-point (name-list db)))
(cond ((or (null? lst) (null? db)) '())
(set! (first no-point) (comp lst (rest db)))
(else (point lst (cdr db))))))
Daddy-sublist has 3 elements in common. Mamma-sublist has 4 elements in common, son-sublist 3 elements and daugther-sublist 1 element.
I want the outdata to be like this:
> (comparison (list 'sneakers 'dress 'pants 'sunglasses 'scarf) family)
'(3 4 3 1)
My code is not functioning as I want it. I get this Eror :
set!: bad syntax in: set!
Can someone guide explain me what to do?
You have bad syntax with set!:
(set! (first no-point-lst) (comparison lst (rest db)))
This is an invalid use of set!, attempting to "mutate the structure" of the list no-point-lst, changing what's actually held in its first position.
set! can't do that. It can be used to change a binding, i.e. the value of a variable: (let ((a 1)) (set! a 2)).
In Common Lisp they can write (setf (first list) newval), but not in Scheme / Racket.
If this is essential to your algorithm, you can use set-car! in R5RS Scheme, or set-mcar! in Racket. Or you could do this with vectors.
But you could also restructure your code as
(set! no-points-list
(cons
(comparison lst (rest db))
(cdr no-points-list)))

Racket - Filter even and odd integers into two separate lists

Function should take a list of integers and return a list containing two sublists -- the first containing the even numbers from the original list, the second containing the odd. My code gets the job done, but if I test it with a negative integer, such as the -5 in the second test, it just gets ignored by my code. Any ideas on how to fix?
(Side note - I know there are functions for even, odd, etc, but for this assignment I am to create them myself.)
(define (segregate lst)
(list(pullEven lst)(pullOdd lst)))
(define (pullEven lst)
(if (empty? lst)
'()
(if (isEven (first lst))
(cons (first lst) (pullEven (rest lst)))
(pullEven (rest lst)))))
(define (pullOdd lst)
(if (empty? lst)
'()
(if (isOdd (first lst))
(cons (first lst) (pullOdd (rest lst)))
(pullOdd (rest lst)))))
(define (isEven x)
(if (equal? (remainder x 2) 0) #t #f)
)
(define (isOdd x)
(if (equal? (remainder x 2) 1) #t #f)
)
;tests
"---------------------------------------------"
"Segregate Tests"
(segregate '(7 2 3 5 8))
(segregate '(3 -5 8 16 99))
(segregate '())
"---------------------------------------------"
Try substituting modulo instead of remainder.
Remainder will preserve the sign of the answer (a remainder of -1 doesn't match the value of 1 that you're checking for).
Modulo returns an answer with the same sign as the denominator.

How to debug "List contains heterogenous data types" in Racket?

Here is my Racket problem:
Define a function that takes a list as an argument. It should return a boolean (i.e. #t or #f) indicating whether the list is sorted in ascending order. You may not use the built-in sorted? function. Your implementation must be recursive.
Input: A list of elements of homogenous data type, either numbers or strings.
Output: A boolean value that indicates whether the elements of the list are sorted in strictly increasing order. If the list contains heterogenous data types, then throw an error (using the error function) with the message “ERROR: List contains heterogenous data types”.
So when I type this function have to gave me this ERROR
(my-sorted? '(7 "spam" 9))
! ERROR: List contains heterogenous data types
BUT for mine its gave me this
(my-sorted? '(7 "spam" 9))
: contract violation
expected: real?
given: "spam"
argument position: 2nd
other arguments...:
Here what I have
(define (my-sorted-int? lst)
(define size (length lst))
(if (< size 2)
#t
(if (null? lst)
#t
(if (> (car lst) (car (rest lst))) <======= Gave me Error
#f
(my-sorted-int? (rest lst) )))))
(define (my-sorted-string? lst)
(define size (length lst))
(if (< size 2)
#t
(if (null? lst)
#t
(if (string>? (car lst) (car (rest lst)))
#f
(my-sorted-string? (rest lst) )))))
(define (my-sorted? lst)
(if (string? (car lst))
(my-sorted-string? lst)
(my-sorted-int? lst)))
So you know the left side is a number since it was the value you initially checked, but the right side also needs to be a number to be able to do > on it. Thus you need something like:
(if (number? (cadr lst))
(if (> (car lst) (cadr lst)) ...)
(error "ERROR: List contains heterogenous data types"))
You might want to use cond to get a flatter structure. Also you have made two identical procedures to deal with integers and strings when you could just made one and pass the things that are different to make your code more DRY:
(define (my-sorted? lst)
(define (my-helper? correct-type? greater-than?)
(let loop ((e (car lst))
(lst (cdr lst)))
(cond ((null? lst) #t)
((not (correct-type? (car lst)))
(error "ERROR: List contains heterogenous data types"))
((greater-than? e (car lst)) #f)
(else (loop (car lst) (cdr lst))))))
(cond ((null? lst) #t)
((string? (car lst)) (my-helper? string? string>?))
(else (my-helper? number? >))))

Lisp - Remove instances from a list of pairs

I want to create a function in lisp that receives a number and a list of pairs and iterates through the list of pairs and removes the ones in which the result of the division between the first element of the pair, and the second element of the same pair is different from the number passed as an argument. In the end it returns a list with only the ones in which the result of the division is the same.
I have the following code so far:
(defun retira-terco(num l1)
(cond ((null l1) ())
((not (equal num (/ (car(first l1)) (cdr(first l1)))))
(retira-terco num (rest l1)))
(t (cons (first l1) (retira-terco num (rest l1))))))
When I try to run this example with a real example I get the following error:
Error: `(1)' is not of the expected type `NUMBER'
What am I doing wrong?
The problem with your code is in this line:
(/ (car(first l1)) (cdr(first l1)))
(car (first l1)) evaluates to a number, but (cdr (first l1)) evaluates to a list. You probably meant (cadr (first l1)).
That said, this code isn't that great from a lispiness point of view. You have a condition you want to filter on. Use higher order programming to express that more like this:
(defun foo (num lst)
(remove-if (lambda (item)
(equal num
(/ (car item)
(cadr item))))
lst)))