How to use the built-in function filter with lambda in Scheme programming? - scheme

"Implement unique, which takes in a list s and returns a new list containing the same elements as s with duplicates removed."
scm> (unique '(1 2 1 3 2 3 1))
(1 2 3)
scm> (unique '(a b c a a b b c))
(a b c)
What I've tried so far is:
(define (unique s)
(cond
((null? s) nil)
(else (cons (car s)(filter ?)
This question required to use the built-in filter function. The general format of filter function is (filter predicate lst), and I was stuck on the predicate part. I am thinking it should be a lambda function. Also, what should I do to solve this question recursively?

(filter predicate list) returns a new list obtained by eliminating all the elements of the list that does not satisfy the predicate. So if you get the first element of the list, to eliminate its duplicates, if they exists, you could simply eliminate from the rest of the list all the elements equal to it, something like:
(filter
(lambda (x) (not (eqv? x (first lst)))) ; what to maintain: all the elements different from (first lst)
(rest lst)) ; the list from which to eleminate it
for instance:
(filter (lambda (x) (not (eqv? x 1))) '(2 1 3 2 1 4))
produces (2 3 2 1 4), eliminating all the occurrences of 1.
Then if you cons the first element with the list resulting from the filter, you are sure that there is only a “copy” of that element in the resulting list.
The last step needed to write your function is to repeat recursively this process. In general, when you have to apply a recursive process, you have to find a terminal case, in which the result of the function can be immediately given (as the empty list for lists), and the general case, in which you express the solution assuming that you have already available the function for a “smaller” input (for instance a list with a lesser number of elements).
Consider this definition:
define (unique s)
(if (null? s)
'()
(cons (first s)
(filter
(lambda (x) (not (eq? x (first s))))
(unique (rest s))))))
(rest s) is a list which has shorter than s. So you can apply unique to it and find a list without duplicates. If, from this list, you remove the duplicates of the first element with filter, and then cons this element at the beginning of the result, you have a list without any duplicate.
And this is a possibile solution to your problem.

Related

How to multiply a list in scheme?

New to scheme but trying to learn the basics.
Let's say I passed a list in as a parameter and I wanted to multiply each element by -1. Right now I have this:
(define (negative b)
(* (car b) -1 )))
Which returns the first element as -1 * that element
So in this case giving it (negative '(5 1 2 3)) returns -5.
But lets say I want it to return
-5 -1 -2 -3
How would I go about making the rest of the list negative? Using cdr recursively?
Do it recursively.
(define (negative l)
(if (null? l)
'()
(cons (* (car l) -1)
(negative (cdr l)))))
If the list is empty, this just returns an empty list, as the base case.
Otherwise, it calculates -1 * the first element, the negative of the rest of the list, and combines them to produce the result.
The purpose of your exercise may be for you to code up your own map procedure, in which case that's fine. But if not, use scheme's built in 'map' procedure which is intended for just this kind of purpose.
'map' has been available at least since R4RS (that is, a long time ago) and possibly earlier.
by using map. If you want it returned as list.
It would be like this
(define negative
(lambda (b)
(map - b)))
Map is going through list b, and apply procedure "-" to each number in list
If you want to return as single numbers not in list you apply values on the list.
(define negative1
(lambda (b)
(apply values (map - b))))
Edit: I saw that you are asking for recursive solution, which would go like this
(define negative1
(lambda (b)
(if (null? b)
'()
(cons (- (car b)) (negative1 (cdr b))))))

Finding the largest list in a definition of lists in lists?

I have a question regarding finding the largest list in a group of lists in scheme.
For example, we define:
(define manylsts (list (list 9 (list 8 7)) 6 (list 5 (list 4 3 2) 1)))
How would I go about finding the largest list in manylsts?
Thank you
You make a procedure that evaluates to zero if it's argument is not a list. (eg. 9), then if its a list you foldl over the elements using length of the argument as accumulator with a lambda that does max between the recursion of the first argument with the accumulator. It would look something like this:
(define (max-children tree)
(if <??>
(foldl (λ (x acc)
(max <??> (max-children <??>)))
(length <??>)
<??>)
0))
Of course there are many ways of doing this, including explicit recursion, but this was the first thing I though of.
I will answer this question as you asked it.
You said you want to
finding the largest list in manylsts
Since you included a non-listed element inside manylsts you want to have a definition that tells you how big is an element (if is a list).
So I wrote the function elemenlen that returns the length of a list if the given element is a list and 0 otherwise.
(define elemenlen
(λ (a)
(if (list? a) (length a) 0)
))
Then I decided I was going to sort them in order of length and then return the first element. So I need a function that returns a boolean value to use it with sort function included in racket/base.
(define list<
(λ (listA listB)
(< (elemenlen listA) (elemenlen listB))))
(define list>
(λ (listA listB)
(not (list< listA listB))))
The first function returns #t if listA is smaller than listB. The second function returns #t if listA is bigger than listB.
Lastly, biggestElement does the whole trick, sorts the elements in list L in descending order (based on length) and returns the first element.
(define biggestElement
(λ (L)
(car (sort L list>)
)))
The function is used like this:
>(biggestElement '((3 2 1) 1 (1 (2 3) 3))
'(1 (2 3) 3)
That is just one way of doing it, there are other ways of doing it, keep it up and tell us if it helped you.
As you see, I decomposed the big problem into little problems. This is a very handy way of doing your DrRacket homework.

How to convert a list into its elements

This must be very easy to accomplish but I am new to racket and dont know how:
I have a list (1 2 3 4) and would like to convert it into (1)(2)(3)(4)
Or is there a way to build it as (1)(2)(3)(4). I am using
cons '(element) call-function
to build it inside a function (recursively)
Try this:
(map list '(1 2 3 4))
From your text, I see that you do '(element). Problem with that is that everything which is quoted is never anything but what you see. Thus if element happens to be a variable it won't be expanded because of the quote.
The right way to get a list with one element would be to use list. eg. (list element) to get whatever the variable element to be the one element in your list. However, you won't need this in a roll-your-own recursive procedure:
(define (listify lst)
(if (null? lst) ; if lst is null we are done
'() ; evaluate to the empty list
(cons (list (car lst)) ; else we make a list with the first element
(listify (cdr lst))))) ; and listify the rest of the list too
Most of the procedure now is facilitating going through the argument, but since it's a common thing to do we can use higher order procedures with foldr so that you only concentrating on what is going to happen with the element in this chain in correspondence with the rest of the process:
(define (listify lst)
(foldr (lambda (e acc)
(cons (list e) ; chain this element wrapped in a list
acc)) ; with the result from the rest of the list
'() ; initiate with an empty list
lst)) ; go through lst
Of course, since we do something with each element in a list and nothing fancy by using map we only need to supply what to do with each element rather telling how to join the chains in the list together as well.
(define (listify lst)
(map list lst)) ; make a new list by applying a list of each element
It's actually a single argument version of zip:
(require srfi/1)
(zip '(1 2 3 4)) ; ==> ((1) (2) (3) (4))
(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))
There you go. As simple as it can get.

Scheme,level intermediate student, find min without recursion

How can I write a function using abstract list functions (foldr, map, and filter) without recursion that consumes a list of numbers (list a1 a2 a3 ...) and produces a new list removing the minimum number from the original list?
The recursion code is:
(define (find-min lst)
(cond
[(empty? (rest lst)) (first lst)]
[else
(local [(define min-rest (find-min (rest lst)))]
(cond
[(< (first lst) min-rest) (first lst)]
[else min-rest]))]))
A fold applies a 2-argument function against a given value and the car of a list uses the result against the successive cars or the cdrs or the list. this is what we want.
Whereas map returns a new list by doing something with each element of a list.
And filter returns a smaller or equal list based on some predicate.
Now just to formulate a function that can choose the lessor of two arguments
(define (the-lessor x y)
(if (< x y)
x
y))
From there implementation is straightforward.
(define (min L) (fold the-lessor (car L) (cdr L)))
Since this looks like a homework question, I'm not going to provide all the code, but hopefully push you in the right direction.
From the HTDP book, we see that "The Intermediate Student language adds local bindings and higher-order functions." The trick here is probably going to using "local bindings".
Some assumptions:
(remove-min-from-list '()) => not allowed: input list must be non-empty
(remove-min-from-list '(1)) => '()
(remove-min-from-list '(1 2 3 1 2 3)) => '(2 3 2 3) ; all instances of 1 were removed
Somehow, we need to find the minimum value of the list. Call this function min-of-list. What are its inputs and outputs? It's input is a list of numbers and its output is a number. Of the abstract list functions, which ones allow us to turn a list of numbers into a number? (And not another list.) This looks like foldl/foldr to me.
(define (min-of-list lst)
(foldr some-function some-base lst))
Since you already showed that you could write min-of-list recursively, let's move on. See #WorBlux's answer for hints there.
How would we use this in our next function remove-min-from-list? What are the inputs and outputs of remove-min-from-list? It takes a list of numbers and returns a list of numbers. Okay, that looks like map or filter. However, the input list is potentially shorter than that output list, so filter and not map.
(define (remove-min-from-list lst)
....
(filter some-predicate list))
What does some-predicate look like? It needs to return #f for the minimum value of the list.
Let's pull this all together and use local to write one function:
(define (remove-min-from-list lst)
(local [(define min-value ...)
(define (should-stay-in-list? number) ...min-value ...)]
(filter should-stay-in-list? lst)))
The key here, is that the definition for should-stay-in-list? can refer to min-value because min-value came before it in the local definitions block and that the filter later on can use should-stay-in-list? because it is in the body of the local.
(define (comparator n) (local [(define (compare v) (not (equal? v n)))] compare))
(define (without-min list) (filter (comparator (foldr min (foldr max 0 list) list)) list))

Another way of writing a mimum value procedure in Scheme?

So if i have the following, which returns the smallest value out of a set of four numbers:
(define (minimum2 a b c d)
(cond ((and (< a b) (< a c) (< a d)) a)
((and (< b c) (< b d)) b)
((< c d) c)
(else d)))
But, I want to write it so that I compare a to b and find the smallest value between those two, then compare c and d, and find the smallest value between those, and then compare those two smallest values together to find the actual minimum. If what I wrote was tough to understand, think of it like a tournament bracket, where a "plays" b, and the winner plays the other winner between c and d. Thank you in advance for the help!
Here's one way to do it:
(define (min4 a b c d)
(define (min2 x y)
(if (< x y) x y))
(min2 (min2 a b) (min2 c d)))
Another way to do it, if you don't want to use an internal function:
(define (min4 a b c d)
(let ((min-ab (if (< a b) a b))
(min-cd (if (< c d) c d)))
(if (< min-ab min-cd) min-ab min-cd)))
Here are two ways to do this. I think that the first, using reduce, is much more idiomatic, but it's not doing the tournament style structure, though it uses the same number of comparisons. The second, which does a tournament style structure, is actually just a special case of a generalized merge-sort. The reason that the number of comparisons is the same is that in the tournament style comparison,
min(a,b,c,d) = min(min(a,b),min(c,d))
and in the reduce formulation,
min(a,b,c,d) = min(min(min(a,b),c),d)
Both require three calls the lowest level min procedure.
A reduce based approach
This solution uses a fold (more commonly called reduce in Lisp languages, in my experience). Scheme (R5RS) doesn't include reduce or fold, but it's easy to implement:
(define (reduce function initial-value list)
(if (null? list)
initial-value
(reduce function (function initial-value (car list))
(cdr list))))
A left-associative fold is tail recursive and efficient. Given a binary function f, an initial value i, and a list [x1,…,xn], it returns f(f(…f(f(i, x1), x2)…), xn-1), xn).
In this case, the binary function is min2. R5R5 actually already includes an n-ary (well, it actually requires at least one arguments, it's at-least-one-ary) min, which means min would already work as a binary function, but then again, if you wanted to use the built in min, you'd just do (min a b c d) in the first place. So, for the sake of completeness, here's a min2 that accepts exactly two arguments.
(define (min2 a b)
(if (< a b)
a
b))
Then our n-ary min* is simply a reduction of min2 over an initial value and a list. We can use the . notation in the argument list to make this a variadic function that requires at least one argument. This means that we can do (min* x) => x, in addition to the more typical many-argument calls.
(define (min* a . rest)
(reduce min2 a rest))
For example:
(min* 4 2 1 3)
;=> 1
A true tournament-style solution based on merge sort
A proper tournament style min is actually isomorphic to merge sort. Merge sort recursively splits a list in half (this can be done in place using the indices of the original list, as opposed to actually splitting the list into new lists), until lists of length one are produced. Then adjacent lists are merged to produce lists of length two. Then, adjacent lists of length two are merged to produce lists of length four, and so on, until there is just one sorted list. (The numbers here don't always work out perfectly if the length of the input list isn't a power of two, but the same principle applies.) If you write an implementation of merge sort that takes the merge function as a parameter, then you can have it return the one element list that contains the smaller value.
First, we need a function to split a list into left and right sides:
(define (split lst)
(let loop ((left '())
(right lst)
(len (/ (length lst) 2)))
(if (< len 1)
(list (reverse left) right)
(loop (cons (car right) left)
(cdr right)
(- len 1)))))
> (split '(1 2 3 4))
((1 2) (3 4))
> (split '(1))
(() (1))
> (split '(1 2 3))
((1) (2 3))
Merge sort is now pretty easy to implement:
(define (merge-sort list merge)
(if (or (null? list) (null? (cdr list)))
list
(let* ((sides (split list))
(left (car sides))
(right (cadr sides)))
(merge (merge-sort left merge)
(merge-sort right merge)))))
We still need the merge procedure. Rather than the standard one that takes two lists and returns a list of their sorted elements, we need one that can take two lists, where each has at most one element, and at most one of the lists may be empty. If either list is empty, the non-empty list is returned. If both lists are non-empty, then the one with the smaller element is returned. I've called it min-list.
(define (min-list l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
(else (if (< (car l1) (car l2))
l1
l2))))
In this case, you can define min* to make a call to merge-sort, where the merge procedure is min-list. Merge-sort will return a list containing one element, so we need car to take that element from the list.
(define (min* a . rest)
(car (merge-sort (cons a rest) min-list)))
(min* 7 2 3 6)
;=> 2

Resources