How do I apply ormap to a single variable? - Scheme - scheme

Working on this project for hours now and I can't figure it out.
I have a list of numbers and I need it to produce true if any of those numbers matches a separate number without using recursion.
(compare-numbers (list 1 2 3) 2) => true
What I know I have to do is use ormap on a local function, but I can't figure out how to make the function.
What I wrote is
(define (comp? num)
(equal? num num-lst)) ;Where num-lst is the list of accepted numbers
But I know I can't use this as ormap needs two lists to work.
Can anyone throw me a hint at solving this?
Thanks.

ormap doesn't need two lists. It just needs a procedure that compares a list element to the given number, which you can create with lambda.
(define (compare-numbers lst num)
(ormap (lambda (n) (equal? n num))
lst))

Related

Why is the empty list produced here in this iteration?

Let's take the following function to get a pair of numbers:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
Why does the above produce '() as the first element of the output? Comparing this with python, I would expect it to just give the three pairs, something like:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
I suppose maybe it has to do with when i is 1?
(map (lambda (j) (list 1 j)) '())
; ()
Is that just an identity in Scheme that a map with an empty list is always an empty list?
When i is 1, the inner map is over (range 1 0), which is () by your own definition. Since map takes a procedure and a list (or lists) of values, applies the procedure to each value in the list in turn, and returns a list containing the results, mapping any procedure over a list containing no values will return a list containing no values.
It might help to create a simple definition for map to see how this might work. Note that this definition is not fully featured; it only takes a single list argument:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
Here, when the input list is empty, there are no values to map over, so an empty list is returned. Otherwise the procedure proc is applied to the first value in the input list, and the result is consed onto the result of mapping over the rest of the list.
A couple of observations:
First, the empty list is not represented by nil in either standard Scheme or vanilla Racket, and you should not be using it. In the early days of Scheme nil was allowed as a crutch for programmers coming from other lisps, but this has not been the case for a long time. I don't think that it was ever in any of the RnRS standards, but nil may have survived in some specific implementations until maybe R4RS (1991). SICP was from that era. Today you should use '() to represent empty list literals in Scheme so that your code can run on any Scheme implementation. Racket's #lang sicp allows code directly from the book to be run, but that should not keep you from using the common notation. Note that Common Lisp does use nil as a self-evaluating symbol to represent both the empty list, and boolean false. Seeing this in Scheme just doesn't look right today.
Second, you will probably be led astray more often than to wisdom by thinking in terms of Python when trying to understand Scheme code. In this particular case, map is an iteration construct, but it is not the same thing as a for loop. A for loop is usually used for side-effects, but map is used to transform a list. Scheme has a for-each form which is meant to be used for its side-effects, and in that sense is more like a for loop. The Python version that is posted above is not at all like the Scheme version, though. Instead of returning the results in a list, the results are printed. In the Scheme code, when i is 1, the inner mapping is over (range 1 0) --> (). But, in the Python code, when i is 1, the inner loop is over range(1, 1), so the body of this for loop is not executed and nothing is printed.
Better to think carefully about the Scheme code you want to understand, falling back on basic definitions, than to cobble together a model based on Python that has possibly unconsidered corner cases.

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.

random integer in scheme

In my OO World, I have an instance of "weapon" class called "max-damage". I asked to create a random number for a variable called "damage".
It says: The amount of "damage" suffered should be a random integer no more than the "max-damage", and at least 1.
I need some help to create that random integer, thanks!
PS: I can't ask more questions, in order to ask this question, I have changed the previous one, sorry..
You got the syntax of filter wrong, it's necessary that you pass a procedure as the first argument. Concretely, the procedure is a predicate (meaning: it evaluates to a boolean value), and the output list will only keep the elements in the original list that evaluate to #t when passed to the procedure. This is what I mean:
(define (remove-divisible lst value)
(filter (lambda (x) (not (zero? (remainder x value))))
lst))
If using a lambda bothers you, it's always possible to define a helper procedure, like this:
(define (remove-divisible lst value)
(define (not-divisible? x)
(not (zero? (remainder x value))))
(filter not-divisible? lst))

accessing elements of list in scheme

How do I change elements of list in Scheme.
I want a procedure to change the minimum elements of a list to another number, so
If I have a procedure called proc and I give it two arguments ( a list and a number), my procedure would work like this:
(proc (list 1 2 3 1) 9) returns '(9 2 3 9). so 9 take the place of the minimum value(s) of the list. I know I can apply min to get the minimum value, but I don't know how to modify a single element of the list.
Since Scheme doesn't have variables to hold values, I thought about using either let or letrec, but I don't know which would be the difference between using let and letrec.
This can be split into two distinct tasks - getting the lowest value in the list, then replacing that value with our new value. We can get the lowest value by running the sort function on our list and sorting by least to greatest, then using apply min to get the first element of the list.
After we've got that, we can use map to go through the list, replacing any instances of the lowest number with our new number. All in all, the complete function should look like this:
(define (replace-least lst new)
(let ((lowest (apply min lst)))
(map (lambda (x) (if (= x lowest) new x)) lst)))
I tested this with DrRacket 5.3 and it performed perfectly as per the specifications provided in your question. If you have any trouble, let me know.
This is an improved, working solution using min:
(define (replace-min lst elt)
(let ((m (apply min lst)))
(map (lambda (x) (if (= x m) elt x))
lst)))
Notice that min is the simplest way to find the minimum element in a list.

Using Scheme to find the least element in a list

(define min
(lambda (l m c)
(cond ((null? l) (print m))
(else ((c (car l))
if((< c m) (m c))
min((cdr l) m c))))))
I want to use the tail-recursive method to do it,but it doesn't work. I'm very very new in Scheme, hope you can help me. Thank you!
This looks like homework, I'll give you some pointers so you can solve it by yourself. Fill-in the blanks:
(define (mymin lst minval)
(cond ((null? lst) ; If the list is empty
???) ; return the minimum value.
((< ??? minval) ; If current element < minimum value
(mymin ??? ???)) ; advance recursion, current element is new minimum.
(else ; If current element >= minimum value
(mymin ??? ???)))) ; advance recursion, keep the same minimum.
In the above code, we're implementing a two-parameter tail-recursive procedure called mymin (don't use the name min, that's a built-in procedure.) The first parameter is the list to traverse; the second parameter stores the minimum value found so far, and when the recursion ends, it will hold the answer.
Call it like this, noticing that for the first call we need to pass in the second argument a number so big that all the other numbers are smaller:
(mymin '(1 2 3 4 0 5) +inf.0)
> 0
Oscar's version will work but I have some stylistic quibbles (this is not a dig at Oscar, who is keeping it simple to make the solution plainer). If you get it working along those lines, see if you can make a couple of changes.
No spurious parameters
You have 3 parameters and Oscar has two but this is a list that takes one input - a list. Give the wrong extra seed parameters and you'll fail. One way to fix this is to recur inside the main function. It could look something like this
(define (mymin lst)
(let ((minval ???))
(define (findmin lst testval)
(cond
(????)
(????)
(????))
(findmin lst minval)))
Do you see how that works? You could initialise minval to inf.0, as Oscar did, or to a special non-numerical value (there are a couple of good choices, one better than the other).
If you're really smart, though, you'll see that there's no need to pass two values each time. You can pass one simple object to each recursion, with no need for an inner function or any initialisation - why initialise anything with infinite values when you have all the data you need at the start?
Here's a clue to how it would look (it starts much like Oscar's version):
(define (mymin lst)
(cond
((null? lst) ???)
((?????) (car lst))
(else (mymin (??????????????????????? lst)))))
There are a few things going on in that last line of ???s ;)
But only try for these improvements once you have a working version, unless you can't get it working any other way. Get it working, then improve - you learn twice ;)
Some things to think about, along the way...
What do you return if there's only one element in the list?
What's the simplest way to test if there's only one element in the list?
What's the most logical thing to return if the list is empty?

Resources