writing filter function using foldr? - scheme

Currently trying to write a filter function that takes a list of procedures and a list of numbers, deletes the procedures that does not return true on every element of the list of numbers.
What I have done is the following, currently taking a single procedure and runs through the list to create a list stating whether the procedure is true or false for each element.
Using foldr, or map if required (non recursive)
(define (my-filter ps xs)
(foldr (λ (x y)
(cons (ps x) y)) '() xs))
How do I delete the procedure if it has at lease one #f?
i.e.
currently
> (my-filter even? '(1 2 3 4))
(#f #t #f #t)
> (my-filter even? (2 4))
(#t #t)
want
> (my-filter (list even?) '(1 2 3 4))
(list)
> (my-filter (list even?) '(2 4))
(list even?)

You can solve this by using Racket's built-in andmap procedure, which tests if a condition is true for all elements in a list - like this:
(define (my-filter ps xs)
(foldr (lambda (f acc)
(if (andmap f xs) ; if `f` is true for all elements in `xs`
(cons f acc) ; then add `f` to the accumulated output
acc)) ; otherwise leave the accumulator alone
'() ; initially the accumulator is an empty list
ps)) ; iterate over the list of functions
Notice that we do not "delete" functions from the output list, instead at each step we decide whether or not we should add them to the output list.
The advantage of foldr is that it preserves the same order as the input list, if that's not a requirement, foldl is more efficient because internally it uses tail recursion. Either way, it works as expected:
(my-filter (list even?) '(1 2 3 4))
=> '()
(my-filter (list even?) '(2 4))
=> '(#<procedure:even?>)

Start with some wishful thinking. Say we have a know of knowing if all xs return #t for any given f
(define (my-filter fs xs)
(foldr (λ (f y)
(if (every? f xs)
(cons f y)
y))
'()
fs))
Now let's define every?
(define (every? f xs)
(cond [(null? xs) #t]
[(f (car xs)) (every? f (cdr xs))]
[else #f]))
Let's check it out for (list even?)
(my-filter (list even?) '(1 2 3 4)) ; ⇒ '()
(my-filter (list even?) '(2 4)) ; ⇒ '(#<procedure:even?>)
Let's add another test in the mix
(define (gt3? x) (> x 3))
(my-filter (list even? gt3?) '(2 4)) ; ⇒ '(#<procedure:even?>)
(my-filter (list even? gt3?) '(4 6)) ; ⇒ '(#<procedure:even?> #<procedure:gt3?>)
Cool !
If you want to see "pretty" procedure names instead of the #<procedure:...> stuff, you can map object-name over the resulting array
(map object-name (my-filter (list even? gt3?) '(4 6))) ; ⇒ '(even? gt3?)
Even though foldl will give you a reversed output, I still think it would be better to use foldl in this case. Just my 2 cents.

Related

Scheme - Recursively Adding up Numbers inside a list of list of list of etc

I am encountering a issue that I need to add up the second number of each list. For example, suppose I have a list of lists like below,
(list (list -4
(list (list -1 4) (list 1 7)))
(list 1 (list (list -2 5) (list 3 3)))
(list 3 12))
Then my job is to add up 4 + 7 + 5 + 3 + 12 = 31. However, the list can have multiple sub lists. But the second item inside a list can either be a number or a list. If it is a list, then we need to dig deeper into this list until we get a number.
Thanks!
Solution
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
(define (my-and x y)
(and x y))
(define (every? l)
(foldr my-and #t l))
(define (flat-list? l)
(cond ((null? l) #t)
((every? (map atom? l)) #t)
(else #f)))
(define (add-only-seconds l)
(define (l-sec-add l acc)
(cond ((null? l) acc)
((atom? l) acc)
((flat-list? l) (+ (second l) acc))
((list? l) (apply + acc (map (lambda (x) (l-sec-add x 0)) l)))))
(l-sec-add l 0))
Example test
(define example-list (list (list -4
(list (list -1 4) (list 1 7)))
(list 1 (list (list -2 5) (list 3 3)))
(list 3 12)))
(add-only-seconds example-list) ;; 31
I used common-lisp-typical functions atom? and every?.
Since and cannot be used in foldr, I defined my-add to make add a function which can be used infoldr`.

Scheme filter but the result list contains indices not values

Is there any easy way to create a kind of filter with the outcome the indices instead of values?
for example:
'(#true #false #true) -> '(0 2)
You can create a custom filter procedure that returns a list of indices for elements of a list where a predicate produces a true value, as such:
(define (filtr pred lst)
(for/list ([i lst]
[n (in-naturals)]
#:when (pred i))
n))
For example,
> (filtr number? '(1 2 3 a b c 8 d 19 e f))
'(0 1 2 6 8)
> (filtr (lambda (x) (and x)) '(#true #false #true))
'(0 2)
Of course there is a way to do it; there's many ways to do it. Here's one way.
(define (func xs)
(let loop ((index 0) (xs xs))
(cond ((empty? xs) empty)
((car xs) (cons index (loop (add1 index) (cdr xs))))
(else (loop (add1 index) (cdr xs))))))
(func '(#true #false #true #false #false #true #true))
;; => '(0 2 5 6)
Racket has a function for this (Not sure if it was present when this question was asked) - indexes-where, in racket/list.
Example:
> (indexes-where '(1 2 0 3 0 4) zero?)
'(2 4)

Scheme: Split list into list of two sublists of even and odd positions

I'm trying to use direct recursion to sort a list into a list of sublists of even and odd positions.
So (split '(1 2 3 4 5 6)) returns ((1 3 5) (2 4 6))
and (split '(a 2 b 3)) returns ((a b) (2 3))
So far, I have the following code:
(define split
(lambda (ls)
(if (or (null? ls) (null? (cdr ls)))
(values ls '())
(call-with-values
(lambda () (split (cddr ls)))
(lambda (odds evens)
(values (cons (car ls) odds)
(cons (cadr ls) evens)))))))
However, now I'm stumped on how to store multiple outputs into a single list.
I know that calling it like this:
(call-with-values (lambda () (split '(a b c d e f))) list)
returns a list of sublists, however I would like the function itself to return a list of sublists. Is there a better way to do this that doesn't involve the use of values and call-with-values?
Sure. Here's an adapted version of your code:
(define (split ls)
(if (or (null? ls) (null? (cdr ls)))
(list ls '())
(let ((next (split (cddr ls))))
(list (cons (car ls) (car next))
(cons (cadr ls) (cadr next))))))
One thing that I like about the code in the question is that it uses odds and evens in a way that reflects the specification.
The objectives of this solution are:
Readability.
To reflect the language of the specification in the code.
To use O(n) space during execution.
It uses an internal function with accumulators and a trampoline.
#lang racket
;; List(Any) -> List(List(Any) List(Any))
(define (split list-of-x)
(define end-of-list (length list-of-x))
;; List(Any) List(Any) List(Any) Integer -> List(List(Any) List(Any))
(define (looper working-list odds evens index)
(cond [(> index end-of-list)
(list (reverse odds)
(reverse evens))]
[(odd? index)
(looper (rest working-list)
(cons (car working-list) odds)
evens
(add1 index))]
[(even? index)
(looper (rest working-list)
odds
(cons (car working-list) evens)
(add1 index))]
[else
(error "split: unhandled index condition")]))
(looper list-of-x null null 1))
Here's an answer that should be clear if you are familiar with match syntax. It is identical in form and function to Chris Jester-Young's answer, but uses match to clarify list manipulation.
#lang racket
(define (split ls)
(match ls
[`(,first ,second ,rest ...)
(match (split rest)
[`(,evens ,odds) (list (cons first evens)
(cons second odds))])]
[_ (list ls '())]))
(: split ((list-of natural) -> (list-of (list-of natural))))
(define split
(lambda (xs)
(list (filter even? xs) (filter odd? xs))))
(: filter ((%a -> boolean) (list-of %a) -> (list-of %a)))
(define filter
(lambda (p xs)
(fold empty (lambda (first result)
(if (p first)
(make-pair first result)
result)) xs)))
(check-expect (split (list 1 2 3 4 5 6)) (list (list 2 4 6) (list 1 3 5)))
i think this one is also really easy to understand..

List of lengths from list of strings using map, filter, or fold-right

You are given a list of strings.
Generate a procedure such that applying this procedure to such a list
would result in a list of the lengths of each of the strings in the
input.
Use map, filter, or fold-right.
(lengths (list "This" "is" "not" "fun")) => (4 2 3 3)
(define lengths (lambda (lst) your_code_here))
I got stuck in the following code and I do not understand how can I use filter.
(define lengths
(lambda (lst)
(if (null? lst)
nil
(fold-right list (string-length (car lst)) (cdr lst)))))
This seems like a work for map, you just have to pass the right procedure as a parameter:
(define (lengths lst)
(map string-length lst))
As you should know, map applies a procedure to each of the elements in the input list, returning a new list collecting the results. If we're interested in building a list with the lengths of strings, then we call string-length on each element. The procedure pretty much writes itself!
A word of advice: read the documentation of the procedures you're being asked to use, the code you're writing is overly complicated. This was clearly not a job for filter, although fold-right could have been used, too. Just remember: let the higher-order procedure take care of the iteration, you don't have to do it explicitly:
(define (lengths lst)
(fold-right (lambda (x a)
(cons (string-length x) a))
'()
lst))
This looks like homework so I'll only give you pointers:
map takes a procedure and applies to to every element of a list. Thus
(define (is-strings lst)
(map string? lst))
(is-strings '("hello" 5 sym "89")) ; (#t #f #f #t)
(define (add-two lst)
(map (lambda (x) (+ x 2)) lst))
(add-two '(3 4 5 6)) ; ==> (5 6 7 8)
filter takes procedure that acts as a predicate. If #f the element is omitted, else the element is in the resulting list.
(define (filter-strings lst)
(filter string? lst))
(filter-strings '(3 5 "hey" test "you")) ; ==> ("hey" "you")
fold-right takes an initial value and a procedure that takes an accumulated value and a element and supposed to generate a new value:
(fold-right + 0 '(3 4 5 6)) ; ==> 18, since its (+ 3 (+ 4 (+ 5 (+ 6 0))))
(fold-right cons '() '(a b c d)) ; ==> (a b c d) since its (cons a (cons b (cons c (cons d '()))))
(fold-right - 0 '(1 2 3)) ; ==> -2 since its (- 1 (- 2 (- 3 0)))
(fold-right (lambda (e1 acc) (if (<= acc e1) acc e1)) +Inf.0 '(7 6 2 3)) ; ==> 2
fold-right has a left handed brother that is iterative and faster, though for list processing it would reverse the order after processing..
(fold-left (lambda (acc e1) (cons e1 acc)) '() '(1 2 3 4)) ; ==> (4 3 2 1)

Andmap\ormap - chez scheme

I tried to find information about andmap & ormap operations in chez scheme.
Still, I don't understand the use of these operations, and what is the difference between it and map.
In pseudo-Scheme,
(andmap f xs) == (fold and #t (map f xs))
(ormap f xs) == (fold or #f (map f xs))
except that:
You can't use and and or in this way.
andmap and ormap can short-circuit processing the list.
That is, except for slightly different short-circuiting behavior,
(andmap f (list x1 x2 x3 ...)) == (and (f x1) (f x2) (f x3) ...)
(ormap f (list x1 x2 x3 ...)) == (or (f x1) (f x2) (f x3) ...)
Petite Chez Scheme Version 8.3
Copyright (c) 1985-2011 Cadence Research Systems
> (define (andmap f xs)
(cond ((null? xs) #t)
((f (car xs))
(andmap f (cdr xs)))
(else #f)))
> (define (ormap f xs)
(cond ((null? xs) #f)
((f (car xs)) #t)
(else (ormap f (cdr xs)))))
> (andmap even? '(2 4 6 8 10))
#t
> (andmap even? '(2 4 5 6 8))
#f
> (ormap odd? '(2 4 6 8 10))
#f
> (ormap odd? '(2 4 5 6 8))
#t
Courtesy of practical-scheme.net:
(ormap procedure list1 list2 ...)
Applies procedure to corresponding elements of the lists in sequence until either the lists run out or procedure returns a true value.
(andmap procedure list1 list2 ...)
Applies procedure to corresponding elements of the lists in sequence until either the lists run out or procedure returns a false value.
http://practical-scheme.net/wiliki/schemexref.cgi/ormap
Figured this was worth putting here, since this StackOverflow question is the first result on Google.

Resources