Why list-ref can not got the correct parameter? - scheme

I wrote a quick-sort in scheme (racket)
#lang racket
(define (quick-sort xs)
(let* ([p (list-ref xs 0)]
[tail (list-tail xs 1)]
[less (filter (lambda (x) (< x p)) tail)]
[greater (filter (lambda (x) (>= x p)) tail)])
(append (quick-sort less) (list p) (quick-sort greater))))
But when I tried it I got this error:
> (quick-sort (list 99 2 9922))
list-ref: index 0 too large for list: '()
I'm new to scheme so I don't quite understand why list-ref can't get the correct input '(99 2 9922)
Edit:
Thanks. I made it work.
#lang racket
(define (quick-sort xs)
(let* ([p (first xs)]
[tail (rest xs)]
[less (filter (lambda (x) (< x p)) tail)]
[greater (filter (lambda (x) (>= x p)) tail)])
(if (equal? (length xs) 1)
xs
(append (quick-sort less) (list p) (quick-sort greater)))))

When designing a recursive algorithm, two things are crucial: your terminating condition and your recursive step, and you don't have a terminating condition. Trace what your code is doing: During your first execution of quick-sort, you'll call:
(append (quick-sort (list 2)) (list 99) (quick-sort (list 9922)))
And the first quick-sort call will in turn invoke (quick-sort '()). Your code doesn't handle the empty list very gracefully, as it will always try to reference the first element of the array as the first thing it does.
Add logic to gracefully handle the empty list.
Also, using first and rest to get the first and remaining elements of a list is considered to be much more pragmatic.

Your code is missing the base case, when the input list is empty. When that happens, list-ref fails with that error.
BTW, note that a better name for (list-ref l 0) is (first l), and similarly (list-tail l 1) is better written as (rest l).
(There's also car and cdr, but if you're a newbie you can ignore them for now.)

You probably already know this, but Racket comes with a built-in sort function too.

Related

Product of squares of odd elements in list in Scheme

I wanted to write a code in Scheme that writes the square odd elements in list.For example (list 1 2 3 4 5) for this list it should write 225.For this purpose i write this code:
(define (square x)(* x x))
(define (product-of-square-of-odd-elements sequence)
(cond[(odd? (car sequence)) '() (product-of-square-of-odd-elements (cdr sequence))]
[else ((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
For run i write this (product-of-square-of-odd-elements (list 1 2 3 4 5))
and i get error like this:
car: contract violation
expected: pair?
given: '()
What should i do to make this code to run properly? Thank you for your answers.
First of all, you need to do proper formatting:
(define (square x) (* x x))
(define (product-of-square-of-odd-elements sequence)
(cond
[(odd? (car sequence))
'() (product-of-square-of-odd-elements (cdr sequence))]
[else
((square (car sequence)) (product-of-square-of-odd-elements (cdr sequence)))]))
Now there are multiple issues with your code:
You are trying to work recursively on a sequence, but you are missing a termination case: What happens when you pass '() - the empty sequence? This is the source of your error: You cannot access the first element of an empty sequence.
You need to build up your result somehow: Currently you're sending a '() into nirvana in the first branch of your cond and put a value into function call position in the second.
So let's start from scratch:
You process a sequence recursively, so you need to handle two cases:
(define (fn seq)
(if (null? seq)
;; termination case
;; recursive case
))
Let's take the recursive case first: You need to compute the square and multiply it with the rest of the squares (that you'll compute next).
(* (if (odd? (car seq)
(square (car seq))
1)
(fn (cdr seq)))
In the termination case you have no value to square. So you just use the unit value of multiplication: 1
This is not a good solution, as you can transform it into a tail recursive form and use higher order functions to abstract the recursion altogether. But I think that's enough for a start.
With transducers:
(define prod-square-odds
(let ((prod-square-odds
((compose (filtering odd?)
(mapping square)) *)))
(lambda (lst)
(foldl prod-square-odds 1 lst))))
(prod-square-odds '(1 2 3 4 5))
; ==> 225
It uses reusable transducers:
(define (mapping procedure)
(lambda (kons)
(lambda (e acc)
(kons (procedure e) acc))))
(define (filtering predicate?)
(lambda (kons)
(lambda (e acc)
(if (predicate? e)
(kons e acc)
acc))))
You can decompose the problem into, for example:
Skip the even elements
Square each element
take the product of the elements
With this, an implementation is naturally expressed using simpler functions (most of which exist in Scheme) as:
(define product-of-square-of-odd-elements (l)
(reduce * 1 (map square (skip-every-n 1 l))))
and then you implement a helper function or two, like skip-every-n.

Simple Scheme, squaring all elements in a list

Okay, I'm new to Scheme and I thought I understood it, but got confused on this problem. I want to square all the elements of a list. So, (mapsq '(1 2 3)) returns (list 1 4 9).
my code:
(define mapsq
(lambda (ls)
(cond ((null? ls) 0)
(else (cons (car ls) (car ls))
(mapsq (cdr ls)))))))
In a practical (non-academic) context, this problem can be easily solved by using the map procedure:
(define mapsq
(lambda (ls)
(map (lambda (x) (* x x))
ls)))
Of course, if this is homework and you need to implement the solution from scratch, I shouldn't spoon-feed the answer. Better find out the solution by yourself, filling-in the blanks:
(define mapsq
(lambda (ls)
(cond ((null? ls) ; If the list is empty
<???>) ; ... then return the empty list.
(else ; Otherwise
(cons (* <???> <???>) ; ... square the first element in the list
(mapsq <???>)))))) ; ... and advance the recursion.
There are two problems in your solution: first, the base case should not return 0 - if we're building a list as an answer, then you must return the empty list. Second, in the recursive step you aren't actually squaring the current element in the list - to do that just multiply it by itself with the * operator.
You could write it like this:
(define (mapsq xs)
(define (square x) (* x x))
(map square xs))
Or this:
(define (mapsq xs)
(map (lambda (x) (* x x)) xs))
Or maybe like this:
(define (mapsq xs)
(let loop ((xs xs) (sqs '()))
(if (null? xs)
(reverse sqs)
(loop (cdr xs) (cons (* (car xs) (car xs)) sqs)))))
Or even like this:
(define (mapsq xs)
(if (null? xs)
'()
(cons (* (car xs) (car xs)) (mapsq (cdr xs)))))
My preference would be the first option. The second option is shorter, but the auxiliary function makes the first option easier to read. I would probably not use either the third or fourth options.
By the way, the solution by laser_wizard doesn't work, either.
I notice that you're new here. If you like an answer, click the up arrow next to the answer so the person who gave the answer gets points; this mark also lets the community of readers know that there is something of value in the answer. Once you have an answer that you are confident is correct, click the check mark next to the answer; that also gives points to the person that gave the answer, and more importantly lets other readers know that you believe this answer most correctly addresses your question.
(define (mapsq xs)
(map * xs xs))
> (mapsq '(1 2 3 4 5))
'(1 4 9 16 25)

implement expand function with racket

I can't seem to figure out how to write this function. What I am trying to write is a function expand that takes a list lst as a parameter of the form '(a (2 b) (3 c)) and is evaluated to '(a b b c c c)
This looks like homework, so I'm not giving you a straight answer. Instead, I'll give you some pointers in the right direction. The most useful hint, is that you should split the problem in two procedures, one for processing the "outer" list and the other for generating the repetitions encoded in the inner sublists.
Notice that both procedures are mutually recursive (e.g., they call each other). The expand procedure recurs over the list, whereas the repeat procedure recurs over the number of repetitions. This is the general structure of the proposed solution, fill-in the blanks:
; input: lst - list to be processed
; output: list in the format requested
(define (expand lst)
(cond ((null? lst) ; if the list is null
'()) ; then return null
((not (pair? (car lst))) ; if the first element of the list is an atom
(cons <???> <???>)) ; cons the atom and advance the recursion
(else ; if the first element of the list is a list
<???>))) ; call `repeat` with the right params
; input: n - number of repetitions for the first element in the list
; lst - list, its first element is of the form (number atom)
; output: n repetitions of the atom in the first element of lst
(define (repeat n lst)
(if (zero? n) ; if the number of repetitions is zero
(expand (cdr lst)) ; continue with expand's recursion
(cons <???> ; else cons the atom in the first element and
<???>))) ; advance the recursion with one less repetition
As this was answered three years ago, I don't think that I am helping with homework. Would just like to point out that the two functions really don't need to be mutually recursive. As replicate is a fairly common function, I would propose:
(define (replicate what n)
(if (zero? n)
(list)
(cons what (replicate what (- n 1)))))
(define (my-expand xs)
(if (empty? xs)
(list)
(let ((x (first xs)))
(if (list? x)
(let ((the-number (first x))
(the-symbol (cadr x)))
(flatten (cons (replicate the-symbol the-number)
(my-expand (rest xs)))))
(cons x (my-expand (rest xs)))))))
Of course it is better to use two lists and perform the flatten at the end, something like this:
(define (my-expand xs)
(define (inner-expander xs ys)
(if (empty? xs) (flatten (reverse ys))
(let ((x (first xs)))
(if (list? x)
(let ((the-number (first x))
(the-symbol (cadr x)))
(inner-expander (rest xs) (cons (replicate the-symbol the-number) ys)))
(inner-expander (rest xs) (cons x ys))))))
(inner-expander xs (list)))

Idiomatic usage of local vs lambda?

In Exercise 30.1.1 of HtDP, I started off using local and then modified it to use lambda in order to answer the question.
(define (add-to-each2 accu a-list)
(cond
[(empty? a-list) empty]
[else (local ((define s (+ accu (first a-list))))
(cons s (add-to-each2 s (rest a-list))))]))
and
(define (add-to-each5 accu a-list)
(cond
[(empty? a-list) empty]
[else (cons ((lambda (x y)
(first (map + (list (first y))
(list x)))) accu a-list)
(add-to-each5 (+ accu (first a-list))(rest a-list)))]))
In this particular instance, to me, the local version is easier to read. Are there situations where the lambda version would be preferred? Thank you.
First off, I think you might be getting relative-2-absolute confused with add-to-each, since add-to-each just adds the same number to each element of the list, rather than incrementing an accumulator. The rest of this post assumes that's the case, and just takes out that incrementing.
I think let would be my first choice for the local binding. Your lambda example uses a common pattern that simulates let using lambda and application:
(let ([x e]) body)
Is equivalent to:
((lambda (x) body) e)
If you use this transformation from lambda to let in your example, you get:
(define (add-to-each5 n a-list)
(cond
[(empty? a-list) empty]
[else (cons (let ([x n] [y a-list])
(first (map + (list (first y))
(list x))))
(add-to-each5 n (rest a-list)))]))
A good compiler will likely generate the same code for this as for your two examples, so it mostly comes down to style. The "left-left lambda" pattern can be more difficult to read, as you note, so I prefer let.
However, Exercise 30.1.1 is trying to make you use map as a replacement for the explicit recursion that occurs in each of your examples. You are using map in your example but only for a single addition at a time, which makes map kind of painful: why bother wrapping up (list (first y)) and (list x) when you just want (+ (first y) x)?
Let's look at a simple definition of map to see how it might be helpful, rather than painful, for this problem:
(define (map f ls)
(cond
[(empty? ls) empty]
[else (cons (f (first ls)) (map f (rest ls)))]))
Right away, you should notice some similarities to add-to-each: the first line of the cond checks for empty, and the second line conses something to do with the first element onto a recursive call to map on the rest. The key, then, is to pass map an f that does what you want to do to each element.
In the case of add-to-each, you want to add a particular number to each element. Here's an example of adding 2:
> (map (lambda (n) (+ 2 n)) (list 1 2 3 4 5))
(3 4 5 6 7)
Notice that map and lambda are both here as 30.1.1 requests, and they act on an entire list without the explicit recursion of the original add-to-each: the recursion is all abstracted away in map.
This should be enough to get you to a solution; I don't want to give away the final answer, though :)

Help understanding Continuations in Scheme

I have been working alongside The Little Schemer to learn Scheme and using PLT-Scheme for my environment.
The Little Schemer has helped me tremendously with recursion (it is straightforward for me now) but I'm stuck on a portion of the book that introduces "collectors" and calls the function as a whole a continuation.
Here is the example code they have used. I understand the recursive elements but I am stuck, in particular on the lambda functions - my mind can't follow the path and how the arguments for that lambda function are set (since their only call is to call them again in recursion, there is no concrete use within the function body).
If someone could more-or-less give me a break down of the path of computation through the recursion of the function into the lambda collectors, that may help me.
;; Build a nested list of even numbers by removing the odd ones from its
;; argument and simultaneously multiply the even numbers and sum the odd
;; numbers that occur in its argument.
(define (even-only-collector l col)
(cond
((null? l)
(col (quote ()) 1 0))
((atom? (car l))
(cond
((even? (car l))
(even-only-collector (cdr l)
(lambda (newl p s)
(col (cons (car l) newl)
(* (car l) p) s))))
(else
(even-only-collector (cdr l)
(lambda (newl p s)
(col newl
p (+ (car l) s)))))))
(else
(even-only-collector (car l)
(lambda (al ap as)
(even-only-collector (cdr l)
(lambda (dl dp ds)
(col (cons al dl)
(* ap dp)
(+ as ds)))))))))
;; The collector function
(define (collector newl product sum)
(cons sum
(cons product newl)))
Thank you in advance!!
Try something simpler to see how this works. For example, here's a version of a list-sum function that receives a continuation argument (which is often called k):
(define (list-sum l k)
(if (null? l)
???
(list-sum (cdr l) ???)))
The basic pattern is there, and the missing parts are where the interesting things happen. The continuation argument is a function that expects to receive the result -- so if the list is null, it's clear that we should send it 0, since that is the sum:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) ???)))
Now, when the list is not null, we call the function recursively with the list's tail (in other words, this is an iteration), but the question is what should the continuation be. Doing this:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) k)))
is clearly wrong -- it means that k will eventually receive the the sum of (cdr l) instead of all of l. Instead, use a new function there, which will sum up the first element of l too along with the value that it receives:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (sum) (+ (car l) sum)))))
This is getting closer, but still wrong. But it's a good point to think about how things are working -- we're calling list-sum with a continuation that will itself receive the overall sum, and add the first item we see now to it. The missing part is evident in the fact that we're ignoring k. What we need is to compose k with this function -- so we do the same sum operation, then send the result to k:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (compose k (lambda (s) (+ s (car l)))))))
which is finally working. (BTW, remember that each of these lambda functions has its own "copy" of l.) You can try this with:
(list-sum '(1 2 3 4) (lambda (x) x))
And finally note that this is the same as:
(define (list-sum l k)
(if (null? l)
(k 0)
(list-sum (cdr l) (lambda (s) (k (+ s (car l)))))))
if you make the composition explicit.
(You can also use this code in the intermediate+lambda student language, and click the stepper button to see how the evaluation proceeds -- this will take a while to go over, but you'll see how the continuation functions get nested, each with it's own view of the list.)
Here's one way to help you "get a more concrete idea". Imagine if the collector were defined thus:
(define (collector l p s)
(display l)
(newline)
(display p)
(newline)
(display s)
(newline))
You can see in the base case, if you pass in an empty list, it will call your function with arguments '(), 1, and 0. Now, work with a one-element list, and see what it'll call your function with. Keep working up with longer and longer lists, until you figure out what's going on.
Good luck!

Resources