How to use foldr in Racket to eliminate numbers in a list that are greater than any subsequent numbers - racket

I have to write a function in Racket using foldr that will take a list of numbers and remove list elements that are larger than any subsequent numbers.
Example: (eliminate-larger (list 1 2 3 5 4)) should produce (1 2 3 4)
I can do it without using foldr or any higher-order functions but I can't figure it out with foldr. Here's what I have:
(define (eliminate-larger lst)
(filter (lambda (z) (not(equal? z null)))
(foldr (lambda (x y)
(cons (determine-larger x (rest lst)) y)) null lst))
)
(define (determine-larger value lst)
(if (equal? (filter (lambda (x) (>= x value)) lst) lst)
value
null)
)
determine-larger will take in a value and a list and return that value if it is greater than or equal to all elements in the list. If not, it returns null. Now the eliminate-larger function is trying to go through the list and pass each value to determine-larger along with a list of every number after it. If it is a "good" value it will be returned and put in the list, if it's not a null is put in the list. Then at the end the nulls are being filtered out. My problem is getting the list of numbers that follow after the current number in the foldr function. Using "rest lst" doesn't work since it's not being done recursively like that. How do I get the rest of the numbers after x in foldr?

I really hope I'm not doing your homework for you, but here goes ...
How do I get the rest of the numbers after x in foldr?
Because you're consuming the list from the right, you can structure your accumulator such that "the rest of the numbers after x" are available as its memo argument.
(define (eliminate-larger lst)
(foldr
(lambda (member memo)
(if (andmap (lambda (n) (<= member n)) memo)
(cons member memo)
memo))
'()
lst))
(eliminate-larger (list 1 2 3 5 4)) ;; (1 2 3 4)
This is admittedly a naive solution, as you're forced to traverse the entire accumulator with each iteration, but you could easily maintain a max value, in addition to your memo, and compare against that each time through.

Following works:
(define (el lst)
(define (inner x lsti)
(if(empty? lsti) (list x)
(if(<= x (apply max lsti))
(cons x lsti)
lsti)))
(foldr inner '() lst))
(el (list 1 2 3 5 4))
Output:
'(1 2 3 4)
The cond version may be preferable:
(define (el lst)
(define (inner x lsti)
(cond
[(empty? lsti) (list x)]
[(<= x (apply max lsti)) (cons x lsti)]
[else lsti] ))
(foldr inner '() lst) )

Related

How do you compare 3 arguments or more in racket?

I know that in Racket to compare for example two numbers you will have something like this.
(define (myMax x y)
(if (< x y) y x))
My question is how do you compare for a function with 3 arguments or more. For example to get the highest number from the arguments.
(define (myMax x y z)
If you want to process an undefined number of elements, you need to work with list.
The idiomatic way is to use recursion to process the elements. Each function call need to process one element (car) and the rest of the list cdr.
You can find an implementation on a another post:
https://stackoverflow.com/a/42463097/10953006
EDIT 1: EXAMPLE
(define (maximum L)
(if (null? (cdr L))
(car L)
(if (< (car L) (maximum (cdr L)))
(maximum (cdr L))
(car L))))
(maximum '( 1 2 3 ))
(maximum '( 1 2 3 4))
(maximum '( 1 2 3 4 5))
Give the results:
3
4
5
EDIT 2: if the real question is about variable number of arguments in Racket, you could use the following notation:
(define (test-function . L)
(printf "~S~%" L)) ;; Here: L is the list (1 2 3)
(test-function 1 2 3)
Which will display (printf):
(1 2 3)

Racket: Product of even number

I am trying to produce the product of the even numbers in a given list.
I am trying to replicate the following example:
Example:
(product-even-numbers '(2 1 6 3 5))
==> 12
This is my version of the definition for product-even-numbers:
(define (product-even-numbers lst)
(define/match (recurse lst accumulator)
;; A _ pattern matches any syntax object
[(_ _) (* car (recurse cdr))])
(recurse lst 1))
I am getting the following error:
(product-even-numbers '(2 1 6 3 5))
. . recurse: arity mismatch;
the expected number of arguments does not match the given number
expected: 2
given: 1
arguments...:
I understand that i am missing the second argument, but I do not know what the second argument is supposed to be.
Why are you using pattern matching? this would be easier to understand without it, and first of all you need to get the recursion and the logic right:
(define (product-even-numbers lst)
(define (recurse lst acc)
(cond ((null? lst) acc)
((even? (car lst)) (recurse (cdr lst) (* (car lst) acc)))
(else (recurse (cdr lst) acc))))
(recurse lst 1))
In this case, it's clear that the second argument is the accumulated product we have so far. And we need to consider three cases: empty list, even element, odd element. For example:
(product-even-numbers '(2 1 6 3 5))
=> 12
(define (product-even-numbers lst)
(local [(define tmp (foldr * 1 (filter even? lst)))]
(if (= 1 tmp) 'nothing tmp)))
If output 1 means no any even number.
(define (product-even-numbers2 lst)
(foldr * 1 (filter even? lst))) ; or use (apply * (filter even? lst))

Racket - Filter even and odd integers into two separate lists

Function should take a list of integers and return a list containing two sublists -- the first containing the even numbers from the original list, the second containing the odd. My code gets the job done, but if I test it with a negative integer, such as the -5 in the second test, it just gets ignored by my code. Any ideas on how to fix?
(Side note - I know there are functions for even, odd, etc, but for this assignment I am to create them myself.)
(define (segregate lst)
(list(pullEven lst)(pullOdd lst)))
(define (pullEven lst)
(if (empty? lst)
'()
(if (isEven (first lst))
(cons (first lst) (pullEven (rest lst)))
(pullEven (rest lst)))))
(define (pullOdd lst)
(if (empty? lst)
'()
(if (isOdd (first lst))
(cons (first lst) (pullOdd (rest lst)))
(pullOdd (rest lst)))))
(define (isEven x)
(if (equal? (remainder x 2) 0) #t #f)
)
(define (isOdd x)
(if (equal? (remainder x 2) 1) #t #f)
)
;tests
"---------------------------------------------"
"Segregate Tests"
(segregate '(7 2 3 5 8))
(segregate '(3 -5 8 16 99))
(segregate '())
"---------------------------------------------"
Try substituting modulo instead of remainder.
Remainder will preserve the sign of the answer (a remainder of -1 doesn't match the value of 1 that you're checking for).
Modulo returns an answer with the same sign as the denominator.

How do I find the index of an element in a list in Racket?

This is trivial implement of course, but I feel there is certainly something built in to Racket that does this. Am I correct in that intuition, and if so, what is the function?
Strangely, there isn't a built-in procedure in Racket for finding the 0-based index of an element in a list (the opposite procedure does exist, it's called list-ref). However, it's not hard to implement efficiently:
(define (index-of lst ele)
(let loop ((lst lst)
(idx 0))
(cond ((empty? lst) #f)
((equal? (first lst) ele) idx)
(else (loop (rest lst) (add1 idx))))))
But there is a similar procedure in srfi/1, it's called list-index and you can get the desired effect by passing the right parameters:
(require srfi/1)
(list-index (curry equal? 3) '(1 2 3 4 5))
=> 2
(list-index (curry equal? 6) '(1 2 3 4 5))
=> #f
UPDATE
As of Racket 6.7, index-of is now part of the standard library. Enjoy!
Here's a very simple implementation:
(define (index-of l x)
(for/or ([y l] [i (in-naturals)] #:when (equal? x y)) i))
And yes, something like this should be added to the standard library, but it's just a little tricky to do so nobody got there yet.
Note, however, that it's a feature that is very rarely useful -- since lists are usually taken as a sequence that is deconstructed using only the first/rest idiom rather than directly accessing elements. More than that, if you have a use for it and you're a newbie, then my first guess will be that you're misusing lists. Given that, the addition of such a function is likely to trip such newbies by making it more accessible. (But it will still be added, eventually.)
One can also use a built-in function 'member' which gives a sublist starting with the required item or #f if item does not exist in the list. Following compares the lengths of original list and the sublist returned by member:
(define (indexof n l)
(define sl (member n l))
(if sl
(- (length l)
(length sl))
#f))
For many situations, one may want indexes of all occurrences of item in the list. One can get a list of all indexes as follows:
(define (indexes_of1 x l)
(let loop ((l l)
(ol '())
(idx 0))
(cond
[(empty? l) (reverse ol)]
[(equal? (first l) x)
(loop (rest l)
(cons idx ol)
(add1 idx))]
[else
(loop (rest l)
ol
(add1 idx))])))
For/list can also be used for this:
(define (indexes_of2 x l)
(for/list ((i l)
(n (in-naturals))
#:when (equal? i x))
n))
Testing:
(indexes_of1 'a '(a b c a d e a f g))
(indexes_of2 'a '(a b c a d e a f g))
Output:
'(0 3 6)
'(0 3 6)

LISP: how to get running sum of a list? (without a global variable)

I am a LISP newbie.
To get the running sum of a list, I am writing like --
(setf sum 0.0)
(mapcar #'(lambda(x)
(setf sum (+ sum x)) sum) values))
For example, if you give '(1 2 3 4) as input, the above code returns '(1 3 6 10) as output and so forth.
Is it possible to do the same thing (in a more elegant way) without using the global variable sum ?
(loop for x in '(1 2 3 4) sum x into y collect y)
scanl is a oneliner:
(defun scanl (f init xs)
(loop for x in xs collect (setf init (funcall f init x))))
You could use loop, like this:
(defun running-sum (xs)
(loop with sum = 0
for x in xs
collect (setf sum (+ sum x))))
(running-sum '(1 2 3 4))
It's fundamentally the same thing, but it uses a local variable instead of a global one, and might be more clear.
Alternatively, you could define a recursive function, and a wrapper function:
(defun running-sum-recursive (xs)
(running-sum-recursive2 0 xs))
(defun running-sum-recursive2 (sum xs)
(if (eq xs nil)
nil
(let ((new-sum (+ sum (car xs))))
(cons new-sum (running-sum-recursive2 new-sum (cdr xs))))))
(running-sum-recursive '(1 2 3 4))
However this seems needlessly complicated to me when loop is available.
Note that in Haskell, you could do a running sum like this:
runningSum xs = scanl1 (+) xs
runningSum [1, 2, 3, 4]
The key here is the scanl1 function. It's possible that something similar exists in Lisp (and we've very nearly written it twice now), but I haven't used Lisp in a while.
Edit: After some searching, I don't think Common Lisp includes anything quite like scanl or scanl1, so here they are:
(defun scanl (f val xs)
(loop for x in xs
collect (setf val (funcall f val x))))
(defun scanl1 (f xs)
(cons (car xs)
(scanl f (car xs) (cdr xs))))
(scanl1 #'+ '(1 2 3 4))
Edit: Thanks to huaiyuan's answer for a suggestion about how the loops could be shortened.
Or you could use higher-order functions
(define (running-sum ls)
(cdr (reverse (foldl (lambda (y xs) (cons (+ (car xs) y) xs)) '(0) ls))))
Haskell does have a rich inventory of functions for list recursion, but we've got reduce at least. Here is an elementary (i. e. without the loop magic) functional solution:
(defun running-sum (lst)
(reverse (reduce (lambda (acc x)
(cons (+ (first acc) x) acc))
(rest lst)
:initial-value (list (first lst)))))
I'm using the head of the original list as the initial value and walk through the rest of the list adding sums at the head (because it's natural to add at the head), finally reversing the list thus obtained.
One can use reduce in most cases when there's a need to traverse a sequence accumulating a value.
Here is an elementary iterative solution using the push-nreverse idiom:
(defun running-sum (lst)
(let ((sums (list (first lst))))
(dolist (x (rest lst))
(push (+ x (first sums)) sums))
(nreverse sums)))
In Scheme I would calculate the sum of the list recursively using an accumulator. Like so:
; Computes a list of intermediary results of list summation
(define list-sum
(lambda (l)
(letrec ((recsum (lambda (lst acc acclst)
(if (pair? lst)
(recsum (cdr lst) (+ acc (car lst)) (cons acc acclst))
(cons acc acclst)))))
(recsum (cdr l) (car l) '()))))
Output:
> (list-sum '(1 2 3 4))
(10 6 3 1)
> (list-sum '(2 4 6 8 10))
(30 20 12 6 2)
>
The trick to recurse over a list is to take the first element/car off each time and pass the rest/cdr. You can keep intermediary results by using an extra parameter (called an accumulator) and pass the sum in that. I've used two accumulators above: one for the last sum and one for a list of all previous sums.
I've never done anything in LISP, so I can't tell if this translates directly to your dialect(?), but it's conceptually simple and I'm sure it's doable in LISP as well.
Do ask if something is not immediately clear. It's been a while since I've used this family of languages :)