accessing elements of list in scheme - 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.

Related

How do I apply ormap to a single variable? - 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))

Scheme language add one to every list element

Here is the problem:
Define a function addOne, which takes a list of numbers and returns a list where each number in the input list is increased by one. For example, (addOne ′(1 2 3 4)) should return (2 3 4 5), and (addOne ′(2 4 6 8)) should return (3 5 7 9).
I'm new for scheme language, need the help. Thank you!
Using map:
(define (add-one nums)
(map (lambda (x) (+ x 1)) nums))
I tried to think of a simple solution to this problem. I created a helper procedure, plus1, which takes in a number and returns the sum of that number and 1:
(define (plus1 x)
(+ x 1))
Then, I defined addOne using map:
(define (addOne lst)
(map plus1 lst))
Basically, map takes in two arguments: a procedure and a list. It applies that procedure to every item of that list, then returns the modified list according to that procedure. In this case, the map part of addOne just takes every item of the inputted list, adds 1 to it, and returns the new list.
Please respond with questions or feedback!

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.

Racket random list-ref function

Define a function that takes a non-empty list and returns an element of the list selected at random and with equal probability. (Do not use the built-in list-ref procedure.)
I'm stuck on this. I feel like you would need to count the number of times the function has run recursively and compare it to the random number you get, but I don't know how to do that in BSL+. Any help would be really great.
Here is a solution. To get the ball rolling the first element of the list is chosen as a candidate to be returned. Then for each element of the remaining elements in the list, we randomly choose if the candidate is to be replaced.
For example: For a list with two elements '(a b) first the element 'a is chosen.
The a coin is flipped: With probability 50% 'b is returned instead.
Examine the code to see how the algorithm works for larger lists:
(define (pick-random xs)
(pick-random/helper (rest xs) (first xs) 1))
(define (pick-random/helper xs chosen k)
(cond
[(empty? xs) chosen]
[else ; with probability 1/(k+1) choose the first element of xs
(if (= (random (+ k 1)) 0)
(pick-random/helper (rest xs) (first xs) (+ k 1))
(pick-random/helper (rest xs) chosen (+ k 1)))]))
If you want to google the theory, this type of algorithm belongs to "sampling algorithms".
I take the comment about not using list-ref as a direction to think about the problem recursively.
An assumption is made that 'equal probability' does not take into account the flaws of naive software-based RNGs.
Note that we use []-notation in the function definition to say that steps, unless specified, will have a (default) value of (random (length lst)). This means it will initially have a random amount of 'steps into' the list.
#lang racket
(define (random-element lst [steps (random (length lst))])
(if (= steps 0)
(first lst)
(random-element (rest lst)
(sub1 steps))))
Since steps is internally specified (as (sub1 steps), subtract one from steps) it will always have an explicit value except when the function is applied like so:
(random-element '(42 1337 128 256))
; 256

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