(scheme) Verify if an element in one list is in the second list with do cicle - scheme

How do we verify in scheme with the do cicle, if an element of the first list is in the second?

The do loop in racket has an interesting structure:
(do ([id init-expr step-expr-maybe] ...)
(stop?-expr finish-expr ...)
expr ...)
The documentation for r5rs provides an example:
(let ((x '(1 3 5 7 9)))
(do ((x x (cdr x))
(sum 0 (+ sum (car x))))
((null? x) sum)))
That statement returns 25, the sum of the elements of the loop. The x in the do loop is initialized to the x in the let, and then iteratively set to the cdr of itself each time through the loop. sum is initialized to 0, and accumulates the value of the car of x each time through. The stopping condition is when the iteration variable is empty, and the return value is the sum.
Ok, aside from the racket preference of square brackets, this looks good. There's a do loop and a list. The loop does something over that list. We can use that to write a function that finds a specific atom in a list (using the racket brackets):
(define (find5 lst)
(do ([x lst (rest x)]
[found #f (or found (eq? 5 (first x)))])
((null? x) found)))
Instead of initializing and adding the value sum, I or into found. Also, I prefer first and rest over car and cdr and define them myself when they don't exist. The way this function works should follow from the explanation of the example.
(find5 '(1 2 3 4 6))
Gives #f, as expected. Similarly:
(find5 '(1 2 3 4 5 6))
Gives #t.
Are you able to generalize finding a specific element in a list with a do loop into your specific question?

Related

Alternating Sum Using Foldr/Foldl (Racket)

Back again with another Racket question. New to higher order functions in general, so give me some leeway.
Currently trying to find the alternating sum using the foldr/foldl functions and not recursion.
e.g. (altsum '(1 3 5 7)) should equal 1 - 3 + 5 - 7, which totals to -4.
I've thought about a few possible ways to tackle this problem:
Get the numbers to add in one list and the numbers to subtract in another list and fold them together.
Somehow use the list length to determine whether to subtract or add.
Maybe generate some sort of '(1 -1 1 -1) mask, multiply respectively, then fold add everything.
However, I have no clue where to start with foldl/foldr when every operation is not the same for every item in the list, so I'm having trouble implementing any of my ideas. Additionally, whenever I try to add more than 2 variables in my foldl's anonymous class, I have no idea what variables afterward refer to what variables in the anonymous class either.
Any help or pointers would be greatly appreciated.
We can leverage two higher-order procedures here: foldr for processing the list and build-list for generating a list of alternating operations to perform. Notice that foldr can accept more than one input list, in this case we take a list of numbers and a list of operations and iterate over them element-wise, accumulating the result:
(define (altsum lst)
(foldr (lambda (ele op acc) (op acc ele))
0
lst
(build-list (length lst)
(lambda (i) (if (even? i) + -)))))
It works as expected:
(altsum '(1 3 5 7))
=> -4
Your idea is OK. You can use range to make a list of number 0 to length-1 and use the oddness of each to determine + or -:
(define (alt-sum lst)
(foldl (lambda (index e acc)
(define op (if (even? index) + -))
(op acc e))
0
(range (length lst))
lst))
As an alternative one can use SRFI-1 List Library that has fold that allows different length lists as well as infinite lists and together with circular-list you can have it alterate between + and - for the duration of lst.
(require srfi/1) ; For R6RS you import (srfi :1)
(define (alt-sum lst)
(fold (lambda (op n result)
(op result n))
0
(circular-list + -)
lst))
(alt-sum '(1 3 5 7))
; ==> -4

Scheme skip or continue during lambda map

I am building a function that takes a set of integers, and returns a subset of the odd integers. I am running into the problem that I need to skip over the even integers in my map, but right now my function returns #<void> instead.
(define (oddSubset set)
(map
(lambda (x)
(cond
((odd? x) x)))
s))
In use:
> (oddSubset '(1 2 3))
'(1 #<void> 3)
Is there logic I can use like "else, continue onto next element"?
Note: I am trying to rewrite the built in filter function
map does not have the possibility to skip, but you can use filter instead:
(filter odd? '(1 2 3 4 5 6)) ; ==> (1 3 5)
Or you can use fold-right
(fold-right (lambda (e acc)
(if (odd? e)
(cons e acc)
acc))
'()
'(1 2 3 4 5 6)) ; ==> (1 3 5)
I assume #!r6rs. Both fold-right and filter are in the library (rnrs lists (6)). There is also SRFI-1 which gives both of these procedures for a R5RS language.
In the none standard language #!racket uses the name foldr in place of fold-right.
map looks like a weird choice for this. By definition it maps a function onto each element in a list and returns the list of the results, so trying to "skip" elements seems unnatural.
filter is what you're looking for.
(filter odd? '(1 2 3))
'(1 3)
map applies a function on all elements. Each invocation of the function is supposed to be independant from the others. Even if you introduce a state with a closure, you can't avoid map to build a list of same size as your input.
You want to (re-)implement the filter function. If you want to do it by yourself, you should try to use foldl and foldr instead.
(cond
((odd? x) x))
map check each element in the list: if it is odd, then return that element. But you did not tell your program what to do when the element is not odd, so map return void.
To solve your problem: use filter instead, since map will return something for each element in the list.
If you want to know how to implement filter, try reading the second chapter of SICP

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.

Writing a function that takes a function as an argument in Racket

This is a hw assignment that requires me to write a scheme function that takes a function(with two params) and a list as parameters, then returns a list where each consecutive pair of the elements of the list is replaced by the value of the function applied to these two elements.
For example - If the list has an odd number of elements, the last element is ignored. For example, (apply-to-pairs (lambda (x y) (+ x y)) '(3 9 5 8 2 4 7)) should return (12 13 6).
so far what I have got is:
(define (fn-name fn l)
(if (null? (cdr l))null
(cons
(fn((car l)(car (cdr l)))
(fn-name fn (cdr l))))))
However, im getting this error in Racket(DrRacket):
application: not a procedure;
expected a procedure that can be applied to arguments
given: 3
arguments...:
9
... and it highlights fn((car lst)(car (cdr lst))). I'm trying to find out how to handle the function parameter. Thanks for the help!
As you already did you just apply fn like you would with any primitives like +. However you have extra parenthesis around (car lst) and (car (cdr lst)) which means you expect first element to also be a procedure you call with the second element as it's only argument and then fn only get one argument (the result of that if 3, 5 or 2 happens to be procedures) Perhaps you instead wanted (fn (car lst) (cadr lst)) (I'm using shothand for car+cdr)
Your base case should check both l and (cdr l) for null since if either one is you are fnished. (Try calling it with (fn-name + '(5))). You can use special form or to do that like (or test1 test2).
Also notice that null is not usually a bound symbol in Scheme. You either need to define it (define null '()) or use '().
EDIT ABout too many results..
Notice that when you have applied the first round withe the first two elements of the list you recurse with a new l starting at the list except the very first element.. That means you then will process 9 and 5 in the next iteration instead of 5 and 8. To fix that you need to use cddr (cdr+cdr) instead of just cdr.

#<Closure> in output

I was writing a function to switch the last element of a list to the beginning:
(define last-elem
(lambda (l)
(car (reverse l))))
(define all-but-last
(lambda (l)
(reverse (cdr (reverse l)))))
(define (last-to-first x) (append (list last-elem x) (all-but-last x)))
(last-to-first '(1 2 3 4 5 6))
It didn't work and I knew why. I forgot to put the brackets around list last-elem x
The thing is, I was curious about the output of the wrongly-typed code:
(#<Closure> (1 2 3 4 5 6) 1 2 3 4 5)
What is the meaning if this? How did it come out to this?
In Racket, the output is
'(#<procedure:last-elem> (1 2 3 4 5 6) 1 2 3 4 5)
which is a little clearer.
A reference to a function is always stored with its referencing environment, a.k.a. as a closure, and your Scheme implementation chooses to display it that way.
(list last-elem x)
doesn't call the function last-elem. It simply returns a list of two elements: the value of the variable last-elem (which is a procedure) and the value of the argument x. You want:
(list (last-elem x))
But there's no reason to make a list in the first place. Try:
(define (last-to-first x)
(cons (last-elem x) (all-but-last x)))
In Scheme, all identifiers denote either a syntactic keyword (bound to a 'transformer') or a variable (bound to a value). In your code last-elem denotes a variable bound to a function, which you defined. When you write:
(list last-elem x)
the interpreter/compiler produces a list with the value of last-elem and x. Thus, the result of #<Closure> in the list.

Resources