How to define my own version of filter procedure in racket? - filter

I am new in Racket and I was assigned to do my own filter procedure. It should work similar to the Racket filter procedure. Currently, my-filter has two arguments: the even procedure to check the items in the list, and a list of items.
So far, I have been only able to check whether the items in the list are even or not. my-filter is supposed to iterate through a list of numbers, retrieve the numbers that are even and save them in a second list. How can I iterate through the list and store the even numbers in the second list?
(define (my-filter f lst)
(if (empty? lst)
empty
(cons
(f (first lst))
(my-filter f (rest lst)))))
> (my-filter even? '(1 2 3 4 5 6))
'(#f #t #f #t #f #t)

There are three cases that you need to consider:
Input list is empty -> we're done.
Current element satisfies the predicate function -> add it to the output and continue with next element.
Current element doesn't satisfy the predicate function -> skip it and continue with next element.
You're mixing the last two cases into a single case. And notice that you must not add (f (first lst)) to the output, that's just the condition that we want to evaluate, we should add (first lst) instead. This is what I mean:
(define (my-filter f lst)
(cond ((empty? lst) empty)
((f (first lst))
(cons (first lst) (my-filter f (rest lst))))
(else (my-filter f (rest lst)))))
It works as expected:
(my-filter even? '(1 2 3 4 5 6))
=> '(2 4 6)

Related

scheme function to filter a list

Write a scheme function that returns a list containing all elements of a given
list that satisfy a given predicate eg. (lambda (x) (< x 5)) '(3 9 5 8 2 4 7) => '(3 2 4)
Any hints how to begin about this ?
Basically you are creating filter.
(define (filter included? lst)
...)
You need to check if the argument has elements and if the first element is to be included or not. Including would involve cons-ing the first element to the recursing with the cdr with the same predicate while not including would not include consing but the exact same thing as the tail in a conse situation.
(filter odd? '(3 4))
; ==> (cons 3 (filter odd? '(4)))
(filter odd? '(4))
; ==> (filter odd? '())
(filter odd? '())
; ==> '()
Putting them together shows that (filter odd? '(3 4)) should produce the result of (cons 3 '())
Here is a skeleton of what I would have done:
(define (filter included? lst)
(cond ((null? lst) <??>)
((included? (car lst)) <??>) ; since it is not null? it has to have at least one element
(else <??>))) ; neither null? nor included? => skip

Return the first and last element in the list Scheme

Pretty straightforward question. My initial approach was to define another procedure to find the last element of lst within first-last. After finding the last element I appended it with the first element of lst (car lst).
This is how append works.
(append list1 list2)
e.g., (append '(1 2 3) '(2 1 5)) -> (1 2 3 2 1 5)
I'm wondering if the problem is just with my syntax but I am not sure.
(define (first-last lst)
(define (last lst)
(cond ((null? (cdr lst))(car lst))
(else (last (cdr lst)))))
(append(car lst)(last lst)))
The error occurs in the
(append(car lst)(last lst)))
"mcar: contract violation
expected: mpair?
given: 1"
This is my first question on stack, so I'm sorry if the question is not presented in the correct way.
append is only for joining two or more lists. Here, though, you're not joining existing lists, but building a list from two elements. For that, use list:
(list (car lst) (last lst))
If you can use match, a neat solution is possible:
(define first-last
(lambda (x)
(match x
((first rest ... last)
(list first last))
((only) (list only only))
(_ #f))))
Of course, you could return something other than #f in the catch-all clause.

Working backwards through a list in scheme

I'm trying to figure out how to work through a list in reverse order (back to front) in Scheme using recursion. My research shows that there is a reverse function that you can use on a list but I would not like to go that route.
I know that the following returns the last element in a list;
(caddr '(1 5 3))
returns 3
I would like to be able to send the remaining 1 5 back through the function, look at the last element again and repeat until the list is exhausted
From left to right is simple enough, you look at the car of the list and send back the cdr.
Do the recursive call first, then the processing of the car. Example:
(define (process-in-reverse lst fun)
(when (not (null? lst))
(process-in-reverse (cdr lst) fun)
(fun (car lst))))
then
> (process-in-reverse '(1 5 3) display)
351
If you just want to reverse the result and if subsequent calls are independent of previous calls, an accumulator will do and is tail-recursive:
(define (process-reverse-result lst fun)
(let loop ((lst lst) (res null))
(if (null? lst)
res
(loop (cdr lst)
(cons (fun (car lst)) res)))))
then
> (process-reverse-result '(1 5 3) add1)
'(4 6 2)

Compare elements in the list

I need compare every second element in the list but I don't know how. Here is an example:
(compare? '(1 x 2 x 3 x 4)) -> #t
(compare? '(1 x 2 x 3 o)) -> #f
I can only compare second and fourth element:
(define compare?
(lambda (list)
(equal? (cadr list) (cadddr list))))
I need 6th, 8th, 10th etc.... I don't know length of the list. Please, help me.
Try this answer, filling-in the blanks:
(define (compare? lst)
(if <???> ; if the list has at most two elements
#t ; then return true
(let ((elt (cadr lst))) ; grab the first element to be compared
(let loop ((lst (cddr lst))) ; step on the second group of elements
(cond (<???> #t) ; if there's only one or zero elements left
(<???> #f) ; if the second element is not equal to `elt`
(else (loop (cddr lst)))))))) ; otherwise continue iterating
Let's look at the example of (compare? '(1 x 2 x 3 x 4)).
You want to ensure that (compare? '(2 x 3 x 4)) is true, and that the 1 x before that also matches.
That then means that you want to ensure that (compare? '(3 x 4)) is true (which it is, by definition), and that the 2 x before that also matches.
Notice how we are working with smaller and smaller lists each time. We can do that because lists have structural induction. Because of structural induction, you don't actually have to know the length of the list. The algorithm just works on smaller and smaller sublists until it hits a base case.
Sample skeletal solution (fill in the <???> with suitable code):
(define (compare? lst)
(if (or (null? lst) (null? (cdr lst)))
#t
(let ((item (cadr lst))
(next (compare? (cddr lst))))
(case next
((#f) <???>)
((#t) <???>)
(else (and <???> <???>))))))
(Technically the #f clause is not necessary, but, it may make it clearer to you what the solution approach should be.)
This solution will only work correctly if the matched slots in the list are not #t or #f. Since you're using symbols in your example, it will work correctly.

removing last element of a list(scheme)

So I have to remove the last element of a list in scheme.
For example, let's say I have a list (1 2 3 4). I need to return:
(1 2 3)
My idea:
reverse(list)
car(list)
reverse(list)
Is there a reverse function in scheme(racket)?
You wrote: "reverse, car, reverse". I believe you meant to write "reverse, cdr, reverse". There's nothing wrong with this solution; it's linear in the size of the list, just like any solution to this that uses the standard lists.
As code:
;; all-but-last: return the list, not including the last element
;; list? -> list?
(define (all-but-last l) (reverse (cdr (reverse l))))
If the multiple traversal of the list or the needless construction of another list copy bothers you, you can certainly avoid it, by writing the thing directly.
Given your almost-solution, I'm going to assume that this isn't homework.
Here's what it would look like, in racket:
#lang racket
(require rackunit)
;; all-but-last : return the list, except for the last element
;; non-empty-list? -> list?
(define (all-but-last l)
(cond [(empty? l) (error 'all-but-last "empty list")]
[(empty? (rest l)) empty]
[else (cons (first l) (all-but-last (rest l)))]))
(check-equal? (all-but-last '(3 4 5))
'(3 4))
There is a reverse, but using it would not be very efficient. I suggest the following recursive function.
(define (remove-last lst)
(if (null? (cdr lst))
'()
(cons (car lst) (remove-last (cdr lst)))))
(remove-last '(1 2 3 4)) ; returns '(1 2 3)
The if checks whether it is at the last element of the list.
SRFI 1 (activate in Racket using (require srfi/1)) has a drop-right function:
(drop-right '(1 2 3 4) 1) ; => (1 2 3)
I would do a recursive function that goes down the list and attaches the element (using cons) if the element after it is not the last, and appends nothing if it isn't.
I haven't done scheme for years though so that's as far as I can go.
Someone can run with how to implement it (unless it's homework then they probably shouldn't!)
I've done something simpler than: reverse(list), car(list), reverse(list) to get the last element, check out:
(define (last-one liste)
(if(null? (cdr liste))
null
(cons (car liste) (last-one (cdr liste)))
)
)
Those who are looking for another way can check this out:
(define (removing-last xx)
(remove (list-ref xx (- (length xx) 1)) xx))
I would write a simple recursion, altering the typical "empty? mylist" base case to "empty? (rest mylist)," so that I can return empty when the input list is only 1 element.
(define (removelast mylist)
(cond
[(empty? (rest mylist)) empty]
[(cons? mylist) (cons (first mylist) (removelast (rest mylist)))]))
(removelast (list 1 2 3 4 5))
By the way, this code is in Racket/PLT Scheme, a subset of Scheme.

Resources