Removing null elements from the scheme list - scheme

(define filter-in
(lambda (predicate list)
(let((f
(lambda (l)
(filter-in-sexpr predicate l))))
(map f list))))
(define filter-in-aux
(lambda (pred lst)
(if (null? lst) '()
(cons (filter-in-sexpr pred (car lst))
(filter-in-aux pred (cdr lst))))))
(define filter-in-sexpr
(lambda (pred sexpr)
(if (equal? (pred sexpr) #t)
sexpr
'())))
Calling (filter-in number? ’(a 2 (1 3) b 7)) produces ( () 2 () () 7).
How I can skip null elements from the generated list to get final outcome of (2 7) ?

The problem is that you're mapping filter-in-sxpr over the list. You can either run another filter pass to remove the nulls, or use a modified filter-in-aux like this:
(define filter-in-aux
(lambda (pred lst)
(if (null? lst) '()
(let ((h (filter-in-sexpr pred (car lst)))
(t (filter-in-aux pred (cdr lst))))
(if (null? h) t
(cons h t))))))

Related

How to create a function that receives a list and creates a new list in Scheme

I'm trying to create a function called evenElememt that takes a list as a parameter and appends all the elements in even positions to a new list and displays the new list.
My attempt:
(define newList '())
(define elementHelper
(lambda lst
((cdr lst)
(cons newList (car lst))
(elementHelper(cdr lst)))
)
)
(define evenElement
(lambda (lst)
(cond
((null? lst) ())
((null? (cdr lst)) ())
(else (elementHelper lst)
(display lst))
)
)
)
Example output: if I enter (evenElement '('a 'b 'c 'f 't 'y)), the output should be (b f y).
This is essentially the same as Can I print alternate elements of a list in Racket?, except that you want to print even positions (1-indexed) instead of odd positions.
(define (even-positions lst)
(cond ((null? lst)
'())
((null? (cdr lst))
'())
(else
(cons (second lst)
(even-positions (cddr lst))))))
(even-positions '(a b c f t y)) returns '(b f y).
Then, this is the function you are looking for:
(define (display-even-positions lst)
(display (even-positions lst)))
You don't need elementHelper. Just make evenElement return the result instead of displaying it.
You also don't need the global variable newList. The function should construct the result as it goes.
(define evenElement
(lambda (lst)
(cond
((null? lst) '())
((null? (cdr lst)) '())
(else (cons (car (cdr lst))
(evenElement (cdr (cdr lst)))))
)
)
)
(display (evenElement '(a b c f t y)))

(remove-if f lst) function on scheme

(remove-all x lst) function that removed anything in lst that was
equal to x. For this problem, write the scheme function (remove-if f lst that returns the list with all elements for which (f x) is true removed.
I have the simple remove-all code as
(define (remove-all x ls)
(if (null? ls)
'()
(if (eq? x (car ls))
(remove-all x (cdr ls))
(cons (car ls)
(remove-all x (cdr ls))))))
But how do I modify it so it takes in a function and returns the list with those elements that return true removed?
Just pass along the comparison predicate as a parameter and replace the hard-coded eq? with the predicate:
(define (remove-if pred ls)
(if (null? ls)
'()
(if (pred (car ls))
(remove-if pred (cdr ls))
(cons (car ls)
(remove-if pred (cdr ls))))))
Or even better, use filter-not in Racket :)
(filter-not even? '(1 2 3 4 5 6))
=> '(1 3 5)

SCHEME Mutable Functions

I've been self-teaching myself Scheme R5RS for the past few months and have just started learning about mutable functions. I've did a couple of functions like this, but seem to find my mistake for this one.
(define (lst-functions)
(let ((lst '()))
(define (sum lst)
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst)
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) sum)
((eq? function 'length) length?)
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
You're not declaring the lst parameter in the procedures that use it, but you're passing it when invoking them. I marked the lines that were modified, try this:
(define (lst-functions)
(let ((lst '()))
(define (sum lst) ; modified
(cond ((null? lst) 0)
(else
(+ (car lst) (sum (cdr lst))))))
(define (length? lst) ; modified
(cond ((null? lst) 0)
(else
(+ 1 (length? (cdr lst))))))
(define (average)
(/ (sum lst) (length? lst)))
(define (insert x)
(set! lst (cons x lst)))
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum lst))) ; modified
((eq? function 'length) (lambda () (length? lst))) ; modified
((eq? function 'average) average)
((eq? function 'insert) insert)
(else
'undefined)))))
Now it works as expected:
(define func (lst-functions))
((func 'insert) 2)
((func 'average))
=> 2
((func 'sum))
=> 2
((func 'length))
=> 1
Some of your functions are recursive but defined without argument. Thus (sum (cdr lst)) shouldn't work since sum uses lst. You could do it by defining a helper:
(define (sum-rec lst)
(if (null? lst)
0
(+ (car lst) (sum-rec (cdr lst)))))
Or perhaps with an accumulator:
(define (sum-iter lst acc)
(if (null? lst)
acc
(sum-iter (cdr lst) (+ (car lst) acc)))
Your sum would of course use it passing the lst:
(define (sum)
(sum-iter lst 0))
Or you can just have the driver partial apply them like this:
(lambda (function)
(cond ((eq? function 'sum) (lambda () (sum-iter lst))
...))
A side note. length? is a strangely named function. A question mark in the end of a name is usually reserved for functions that return a true or a false value and this clearly returns a number.

Scheme quick-sort with filter

I need to write the function (quick-sort pred lst)
lst is the list of numbers to be sorted
pred is the predicate by which the list is ordered, the signature of this predicate is: (lambda (x y) …)
- (quick-sort < lst) will sort ascending (small to large)
- (quick-sort > lst) will sort descending (large to small)
- (quick-sort (lambda (x y) (< (car x) (car y))) lst) will sort a list
with inner lists according to the first element of the inner list, ascending.
I started with regular quick-sort:
(define (quick-sort lst)
(cond
((null? lst) '())
((= (length lst) 1) lst)
(else (append (quick-sort (filter (lambda (n) (< n (car lst))) lst))
(list (car lst))
(quick-sort (filter (lambda (n) (> n (car lst))) lst))))))
And now I'm trying to do this with pred:
(define (quick-sort pred lst)
(define (quick-sort-help lst)
(cond ((null? lst) ())
((= (length lst) 1) lst)
(else
(append (quick-sort-help (filter (lambda (n) (pred n (car lst))) lst))
(list (car lst))
(quick-sort-help (filter (lambda (n) (not(pred n (car lst)))) lst)))))) (quick-sort-help lst))
And I get an infinite recursion or something.
Can you help me solve this problem please?
Thanks!
First of you don't need the helper function quick-sort-help.
It recurs infinitely because you apply your helper function to lst instead cdr lst. In your regular quicksort you have (filter (lambda (n) (< n (car lst))) and (filter (lambda (n) (> n (car lst))). But then in the one with the predicate you have the problem that (not (pred ...) would cover the cases for <= and not < if the predicate is > and vice versa. So it gets stuck because the first element in the list is always equal with itself.
Here a correct quicksort:
(define (qsort f lst)
(if (null? lst)
null
(let ([pivot (car lst)])
(append (qsort f (filter (λ (n) (f n pivot)) (cdr lst)))
(list pivot)
(qsort f (filter (λ (n) (not (f n pivot))) (cdr lst)))))))

Scheme function that returns a function

I need to write a scheme function that returns as a function which then takes another argument, eg a list and in turn return the desired result. In this example (c?r "arg") would return -- (car(cdr -- which then subsequently takes the list argument to return 2
> ((c?r "ar") '(1 2 3 4))
2
> ((c?r "ara") '((1 2) 3 4))
2
The problem I have is how can I return a function that accepts another arg in petite?
Here's how you might write such a function:
(define (c?r cmds)
(lambda (lst)
(let recur ((cmds (string->list cmds)))
(if (null? cmds)
lst
(case (car cmds)
((#\a) (car (recur (cdr cmds))))
((#\d) (cdr (recur (cdr cmds))))
(else (recur (cdr cmds))))))))
Note that I'm using d to signify cdr, not r (which makes no sense, to me). You can also write this more succinctly using string-fold-right (requires SRFI 13):
(define (c?r cmds)
(lambda (lst)
(string-fold-right (lambda (cmd x)
(case cmd
((#\a) (car x))
((#\d) (cdr x))
(else x)))
lst cmds)))
Just wanted to add my playing with this. Uses SRFI-1.
(import (rnrs)
(only (srfi :1) fold)) ;; require fold from SRFI-1
(define (c?r str)
(define ops (reverse (string->list str)))
(lambda (lst)
(fold (lambda (x acc)
((if (eq? x #\a) car cdr) ; choose car or cdr for application
acc))
lst
ops)))
Its very similar to Chris' version (more the previous fold-right) but I do the reverseso i can use fold in the returned procedure. I choose which of car or cdr to call by looking at the character.
EDIT
Here is an alternative version with much more preprocessing. It uses tail-ref and list-tail as shortcuts when there are runs of #\d's.
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (reverse
(if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs)))))
(lambda (lst)
(fold (lambda (fun lst)
(fun lst))
lst
funs))))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
This can be made even simpler in #!racket. we skip the reverse and just do (apply compose1 funs).
(define (c?r str)
(let loop ((druns 0) (ops (string->list str)) (funs '()))
(cond ((null? ops)
(let ((funs (if (zero? druns)
funs
(cons (lambda (x)
(list-tail x druns))
funs))))
(apply compose1 funs)))
((eq? (car ops) #\d) (loop (+ druns 1) (cdr ops) funs))
((= druns 0) (loop 0 (cdr ops) (cons car funs)))
(else (loop 0 (cdr ops) (cons (lambda (x)
(list-ref x druns))
funs))))))
Assuming a compose procedure:
(define (compose funs . args)
(if (null? funs)
(apply values args)
(compose (cdr funs) (apply (car funs) args))))
(compose (list cdr car) '(1 2 3 4))
=> 2
c?r can be defined in terms of compose like so:
(define (c?r funs)
(lambda (e)
(compose
(map
(lambda (f) (if (char=? f #\a) car cdr))
(reverse (string->list funs)))
e)))
then
((c?r "ar") '(1 2 3 4))
=> 2
((c?r "ara") '((1 2) 3 4))
=> 2

Resources