Reputation: 13
I'm trying to write a function that checks if a given list is spiraling (numbers going from negative to positive while the abs value of the numbers is strictly increasing)
EX:
(check-expect
(spiraling? (cons 1 (cons -10 (cons 100 empty))))
true)
Im not entirely sure even where my error is so i made slight adjustments in my writing that hasnt done anything.
(define (spiraling? list-of-int)
(cond
[(empty? list-of-int) true]
[(and (number? (first list-of-int))
(empty? (rest list-of-int))) true]
[(and (< (abs (first list-of-int))
(abs (first (rest (first list-of-int)))))
(cond
[(and (> 0 (first list-of-int))
(< 0 (first (rest (first list-of-int)))))true]
[(and (< 0 (first list-of-int))
(> 0 (first (rest (first list-of-int)))))true]
[else false]))
(cond
[(empty? list-of-int) true]
[else (spiraling? (rest list-of-int))])]))
(check-expect
(spiraling? (cons 1 (cons -10 (cons 100 empty))))
true)
(check-expect
(spiraling? (cons -1 (cons 2 (cons -3 (cons 4 empty)))))
true)
(check-expect
(spiraling? (cons 99 (cons -100 (cons 100 empty))))
false)
(check-expect
(spiraling? (cons 0 (cons -10 (cons 100 empty))))
false)
But instead it comes out as:
:: rest: expects a non-empty list; given: ()
Upvotes: 1
Views: 1179
Reputation: 27424
Your program has many incoherences.
First, the argument of the function should be a list of integers, but sometimes you use it as a list of lists, for instance when you write:
(abs (first (rest (first list-of-int)))))
in fact (first list-of-int)
should return an integer (the first element of the list), but then you apply to it rest
, which is an operator that applied to a non empty list returns the list without the first element. And this is the reason of the error message (“rest expect a non-empty list but received 1”).
If you want the second element of a list, you can do (first (rest list))
, or, better, (second list)
. These are basic operators of the language.
Second, in the second branch of the cond
, you check to see if the first element of the list is a number, but this check is not repeated in the third branch, even if you use both the first and the second elment as numbers. So the test is useless, since it is applied only in certain cases to certain elements of the list. You should apply to all or none of the elements, to be consistent.
Third, in the last branch of the cond, in the last two lines, you check again if the list is empty, but at this point of the program the list is certainly not empty, since you have tested at least two elements!
Here is a possible solution (without checking if all the elements are numbers):
(define (spiraling? list-of-int)
(if (or (empty? list-of-int) (empty? (rest list-of-int)))
true
(let ((first-element (first list-of-int))
(second-element (second list-of-int)))
(if (or (< first-element 0 second-element)
(> first-element 0 second-element))
(spiraling? (rest list-of-int))
false))))
Upvotes: 1