Can't figure out what is wrong with "sort" - scheme

I'm trying to find out the smallest difference between two number in a sorted list so I wirte
(define (smallest-dif lst)
(cond
[(empty? lst) empty]
[(empty? (rest lst)) (smallest-dif (rest lst))]
[else (first (sort (cons (-(second lst) (first lst)) (smallest-dif (rest lst))) <))]))
My example is: (smallest-dif '(5 500 505 600 650 10000))
but drracket tells me this:sort: contract violation
expected: list?
given: '(50 . 9350)
I dont know what's wrong with my code. If I take out "first", the program can run properly.
Can anyone help me? thx.

Let’s look at what this part of the code is doing:
(sort (cons (-(second lst) (first lst)) (smallest-dif (rest lst))) <)
Say your list is '(1 2 3). Let’s work out part of the evaluation by hand:
(sort (cons (- 2 1) (smallest-dif '(2 3))) <)
(sort (cons 1 (first (sort (cons (- 3 2) (smallest-dif '(2))) <))) <)
(sort (cons 1 (first (sort (cons 1 empty) <))) <)
(sort (cons 1 1) <)
It’s trying to sort a cons cell, not a list, which is the contract violation it’s complaining about.

The problem with your code is that it sorts and takes the first of every part of the list. You need to split them up into one that returns just the diffs and one that does the sorting and picking.
(define (diffs lst)
(cond
[(or (empty? lst) (empty? (rest lst))) empty]
[else (cons (- (second lst) (first lst)) (diffs (rest lst)))]))
Then you can make your smallest-dif that uses that procedure in order to pick the smallest either the way you did with sorting and picking the first or you may use min.

Related

Buidling BST in racket from a list

I introduce today is to make a BST tree using a list. This is a list with sorted version, and strictly increasing, with no duplicates. like (list 100 200 300 400)..
Ialready write alot of code. It is here. but nothing is works..Can some one change it to fix?
Thank you
(define (bst-tree lst)
(cond
[(empty? lst) empty]
[else
(local [(define (pivot lst)
(cond
[(= 1 (length lst)) (first lst)]
[(= 2 (length lst)) (first lst)]
[else (pivot (rest (foldl cons empty (rest (foldl cons empty lst)))))]))
(define less (filter (lambda (x) (< x (pivot lst))) lst))
(define greater (filter (lambda (x) (> x (pivot lst))) lst))]
(append (make-node pivot (bst-tree less) (bst-tree greater))))]))
Here is the fix: (append (make-node(pivot lst)(bst-tree less) (bst-tree greater)))
pivot refers to the function, and therefore evaluates to a procedure applying it on the list gets the numeric value.

How to find if a list consists of ordered perfect squares in scheme?

I want to return true if the list is a square list, that is, true if the list is of the type '(0 1 4 9 16).
This is what I have (below) but it does check if the list is ordered. That is, my code will return true if a list is '(4 0 1 9 16). How can I modify my code?
(define (squares? lst)
(cond
((null? lst) #t)
((not( integer? (sqrt(car lst)))) #f)
(else (squares? (cdr lst)))))
for a list of the type '(4 0 1 9 16) I am going to obtain true with the above code, but the answer should be false, because my list is not '(0 1 4 9 16). Thanks in advance.
In the true spirit of functional programming, you should attempt to split the problem in smaller parts, and to reuse and combine existing procedures.
Assuming that the list doesn't need to be "complete", we just need to create and invoke one extra procedure that checks if the list is sorted:
(define (square? lst)
(and (all-squares? lst)
(sorted? lst)))
(define (all-squares? lst)
(cond
((null? lst) #t)
((not (integer? (sqrt (car lst)))) #f)
(else (all-squares? (cdr lst)))))
(define (sorted? lst)
(apply <= lst))
Just for fun, we can also rewrite all-squares? taking advantage of existing procedures:
(define (square? lst)
(and (andmap (compose integer? sqrt) lst)
(apply <= lst)))
Anyway, it'll work as expected with either implementation:
(square? '(0 1 4 9 16))
=> #t
(square? '(4 0 1 9 16))
=> #f
You could pass additionally last checked number
(define (squares? lst last-n)
and then check if (car lst) is bigger than last-n
((not (< last-n (car lst)) #f)
Oh, and also, don't forget to pass new last-n to squares?
(else (squares? (cdr lst) (car lst)))
You can define last-n as optional parameter, ie (define (squares? lst . last-n)) but then you have to access value by (car last-n), because all optional parameters are passed joined together as a list.

Reversed output in tail recursion

(define (sqr-tail lst)
(define (helper lst res)
(if (null? lst)
res
(cond ((list? (car lst))
(helper (cdr lst)
(cons (helper (car lst) ())
result)))
(else (helper (cdr lst)
(cons (expt (car lst) 2) res))))))
(helper lst ()))
I have this tail recursion function in scheme which sqr every element in the list, but unfortunately the result is reversed to what I suppose to output.
for input :
> (sqr-tail (list 1 2 4 3 (list 1 2 (list 1)) 3 3))
the output :
< (9 9 ((1) 4 1) 9 16 4 1)
thanks.
This is something that is inherent in the way Lisp/Scheme lists work: because there are only really conses, the way to build up lists is backwards. So the common tail-recursive-loop-with-an-accumulator approach as you've used ends up building the result backwards. The simple answer to this is that you need to reverse the result when you return it, and in your case, since you are recursing (not tail-recursing) into nested lists as well you need to reverse them as well of course.
Here is a somewhat cleaned-up and error-protected version of your original function (note this was written in Racket -- it may not be quite legal Scheme, but it is close):
(define (square-nested-list/reversed l)
(define (snl-loop lt accum)
(cond [(null? lt)
accum]
[(cons? lt)
(let ([head (car lt)]
[tail (cdr lt)])
(cond [(list? head)
(snl-loop tail (cons (snl-loop head '())
accum))]
[(number? head)
(snl-loop tail (cons (* head head) accum))]
[else (error "mutant horror death")]))]
[else (error "mutant death horror")]))
(snl-loop l '()))
So to get the result forwards we need to reverse the accumulator when we return it. This is a very small change to the above function:
(define (square-nested-list/forward l)
(define (snl-loop lt accum)
(cond [(null? lt)
(reverse accum)]
[(cons? lt)
(let ([head (car lt)]
[tail (cdr lt)])
(cond [(list? head)
(snl-loop tail (cons (snl-loop head '())
accum))]
[(number? head)
(snl-loop tail (cons (* head head) accum))]
[else (error "mutant horror death")]))]
[else (error "mutant death horror")]))
(snl-loop l '()))
If you want to be annoyingly clever and purist you can now notice that the tail-recursive-loop-with-accumulator approach produces results in reverse, so the trivial case of it is, in fact, reverse:
(define (square-nested-list/forward/stupidly-purist l)
(define (rev l)
(define (rev-loop lt a)
(if (null? lt) a (rev-loop (cdr lt) (cons (car lt) a))))
(rev-loop l '()))
(define (snl-loop lt accum)
(cond [(null? lt)
(rev accum)]
[(cons? lt)
(let ([head (car lt)]
[tail (cdr lt)])
(cond [(list? head)
(snl-loop tail (cons (snl-loop head '())
accum))]
[(number? head)
(snl-loop tail (cons (* head head) accum))]
[else (error "mutant horror death")]))]
[else (error "mutant death horror")]))
(snl-loop l '()))
People who do this are generally just trying to score points on the internet though (there are even more stupidly pure approaches for which you get more points).
And here are the results of calling those three functions:
> (define test-data '((1 2 3) (4 5) 6))
> (displayln (square-nested-list/reversed test-data))
(36 (25 16) (9 4 1))
> (displayln (square-nested-list/forward test-data))
((1 4 9) (16 25) 36)
> (displayln (square-nested-list/forward/stupidly-purist test-data))
((1 4 9) (16 25) 36)
Some other approaches
One issue with this 'reverse the result' is that it involves walking the result to reverse it, and also making a copy of it. Once upon a time this was something that was a real problem, because machines had only a tiny amount of memory and were very slow. Indeed, if your lists are enormous it still is a problem. More commonly it is a problem which exists in the minds of people who either, like me, remember machines which were very slow and had only tiny memory, or whose minds have been damaged by languages which encourage you to behave as if you were using such machines ('C programmers know the cost of everything but the value of nothing').
One partial answer to this problem offered by older Lisps is a function which is like reverse but works destructively: it reverses a list in place, destroying the original structure. This function is called nreverse in Common Lisp. If it existed in Scheme it would be called reverse! I suppose.
A more complete answer is to build the list forwards in the first place. You do this by trickery involving keeping a reference to the final cons of the list, and repeatedly replacing its cdr with a new final cons whose car is the object you are collecting. If you want to do this without your code looking horrible you need to use a macro: the one I wrote (for Common Lisp, not Scheme) was called collecting as it collected lists forwards. There are many others. Note that this approach requires mutable conses and also is not clearly efficient in the presence of modern garbage collectors.
Macros like collecting still have their place I think: not because they make your code faster, but because they can make it clearer: if you want collect some results into a list, then do that, don't do this weird reversing thing.
You are almost there.
All you need to do is reverse the return value for each sublist:
(defun sqr-tail (lst)
(labels ((helper (lst res)
(cond ((null lst)
(reverse res))
((listp (car lst))
(helper (cdr lst)
(cons (helper (car lst) ())
res)))
(t (helper (cdr lst)
(cons (expt (car lst) 2) res))))))
(helper lst ())))
(sqr-tail (list 1 2 4 3 (list 1 2 (list 1)) 3 3))
==> (1 4 16 9 (1 4 (1)) 9 9)
or, in scheme:
(define (sqr-tail lst)
(define (helper lst res)
(cond ((null? lst)
(reverse res))
((list? (car lst))
(helper (cdr lst)
(cons (helper (car lst) ())
res)))
(else (helper (cdr lst)
(cons (expt (car lst) 2) res)))))
(helper lst ()))

Sum of all numbers in a list at the top level

I'm new to Scheme and I've spent about a week on this.
Write a Lisp function sumlist which takes a list and returns the sum of all the numbers in the list, at the top level. Thus,
(sumlist '(1 2 (3) (4 a) nil b 5)) should return 1+2+5=8. The numbers 3 and 4 are not at the top level. Use number? to check if a thing is a number."
This is what I have so far. It can recognize whether something is a number or not, but I can't get it to only add up the numbers on the top level.
(define (sumlist lst)
(cond ((null? lst) 0)
((number? lst) lst)
((list? lst)
(+ (sumlist (car lst)) (sumlist (cdr lst))))
(#t 0)))
; no values returned
> (sumlist '(1 2 (3) (4 a) nil b 5))
15
Any help is appreciated.
EDIT: Both Jedi's and Daniel's answers work. Thank you both very much.
I think it can be a bit simpler:
(define (sumlist lst)
(cond
((null? lst) 0)
((number? (car lst)) (+ (car lst) (sumlist (cdr lst))))
(else (sumlist (cdr lst)))))
Since you only care if an element is a number or not, you only have 3 cases.
(define (sumlist lst)
(cond ((null? lst) 0) ;; list is empty, we're done ;;
((number? (car lst)) (+ (car lst) (sumlist (cdr lst)))) ;; the first item is a number, so we add it to the rest
(else (sumlist (cdr lst))) ;; the first item was not a number, we just check the rest of the list
))

removing last element of a list(scheme)

So I have to remove the last element of a list in scheme.
For example, let's say I have a list (1 2 3 4). I need to return:
(1 2 3)
My idea:
reverse(list)
car(list)
reverse(list)
Is there a reverse function in scheme(racket)?
You wrote: "reverse, car, reverse". I believe you meant to write "reverse, cdr, reverse". There's nothing wrong with this solution; it's linear in the size of the list, just like any solution to this that uses the standard lists.
As code:
;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
If the multiple traversal of the list or the needless construction of another list copy bothers you, you can certainly avoid it, by writing the thing directly.
Given your almost-solution, I'm going to assume that this isn't homework.
Here's what it would look like, in racket:
#lang racket
(require rackunit)
;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
(cond [(empty? l) (error 'all-but-last "empty list")]
[(empty? (rest l)) empty]
[else (cons (first l) (all-but-last (rest l)))]))
(check-equal? (all-but-last '(3 4 5))
'(3 4))
There is a reverse, but using it would not be very efficient. I suggest the following recursive function.
(define (remove-last lst)
(if (null? (cdr lst))
'()
(cons (car lst) (remove-last (cdr lst)))))
(remove-last '(1 2 3 4)) ; returns '(1 2 3)
The if checks whether it is at the last element of the list.
SRFI 1 (activate in Racket using (require srfi/1)) has a drop-right function:
(drop-right '(1 2 3 4) 1) ; => (1 2 3)
I would do a recursive function that goes down the list and attaches the element (using cons) if the element after it is not the last, and appends nothing if it isn't.
I haven't done scheme for years though so that's as far as I can go.
Someone can run with how to implement it (unless it's homework then they probably shouldn't!)
I've done something simpler than: reverse(list), car(list), reverse(list) to get the last element, check out:
(define (last-one liste)
(if(null? (cdr liste))
null
(cons (car liste) (last-one (cdr liste)))
)
)
Those who are looking for another way can check this out:
(define (removing-last xx)
(remove (list-ref xx (- (length xx) 1)) xx))
I would write a simple recursion, altering the typical "empty? mylist" base case to "empty? (rest mylist)," so that I can return empty when the input list is only 1 element.
(define (removelast mylist)
(cond
[(empty? (rest mylist)) empty]
[(cons? mylist) (cons (first mylist) (removelast (rest mylist)))]))
(removelast (list 1 2 3 4 5))
By the way, this code is in Racket/PLT Scheme, a subset of Scheme.

Resources