Extract elements from list - scheme

I am trying to extract all elements that are of symbol 'sym
from a list.
(define (extract-sym list)
extract-sym-inner (list null))
(define (extract-sym-inner oldList newList)
(cond (null? oldList
(newList))
(eq? (car oldList) newList
(extract-sym-inner((cdr oldList) append newList (extract-sym(oldList)))))
(eq? (car oldList) 'sym
(extract-sym-inner((cdr oldList) cons newList(car oldList))))
(else
(extract-sym-inner(cdr oldList newList)))))
What I'm trying to do is:
Send the list into an inner function and then:
1. if it's null, return the new list
2. else if the element itself is a list, append the list from the outer function to the new list and continue to next element of old list
3. else if the element is of symbol 'sym, insert it to the new list and continue to the next element of old list
4. else continue to the next element of old list
I think the algorithm itself should work, but I can't manage to understand all the compilation errors I'm getting. For example (extract-sym '(1 2 sym)) gives me the error application: not a procedure;
Any comment would help..

There are lots of syntax errors in your code (mostly dealing with incorrect usage of brackets). As mentioned in the comments, you should spend some time familiarizing yourself with the syntax of the language before tackling any other problem. Having said that, this is what I believe you intended to do, study the following solution and pay attention to those brackets!
(define (extract-sym lst) ; don't use "list" as a parameter name
(cond ((null? lst) '()) ; if list is empty, return empty list
((eq? (car lst) 'sym) ; if current element is 'sym
(cons (car lst) ; add it to the output using cons
(extract-sym (cdr lst)))) ; and advance recursion
((pair? (car lst)) ; if current element is a list
(append (extract-sym (car lst)) ; recursively process and use append
(extract-sym (cdr lst)))) ; also, advance recursion
(else (extract-sym (cdr lst))))) ; otherwise just advance recursion
For example:
(extract-sym '(1 sym 2 (3 sym 4) (5) sym))
=> '(sym sym sym)

Related

Implementing powerset in scheme

I am trying to implement a powerset function in Scheme in two ways.
One way is using tail recursion, and I did it like this:
(define (powerset list)
(if (null? list) '(()) ;; if list is empty, its powerset is a list containing the empty list
(let ((rest (powerset (cdr list)))) ;; define "rest" as the result of the recursion over the rest of list
(append (map (lambda (x) (cons (car list) x)) rest) ;; add the first element of list to the every element of rest (which is a sublist of rest)
rest)))) ;; and append it to rest itself (as we can either use the current element (car list), or not
Which works fine.
Another way is using foldr, and this is where I face some issues.
My current implementation is as follows:
(define (powerset-fr list)
(foldr (lambda (element result) ;; This procedure gets an element (and a result);
(if (null? result) ;; if starting with the empty list, there is nothing to "fold over".
(cons '() (cons element result))
(foldr (lambda (inner-element inner-result)
(append (cons element result) inner-result))
'(())
result)))
'() ;; The result is initialized to the empty list,
list)) ;; and the procedure is being applied for every element in the first list (list1)
Which yields a poor result.
I'll try to explain shortly how did I approach this problem so far:
foldr runs over every element in the given set. For each such element, I should add some new elements to the powerset.
Which elements should these be? One new element for each existing element in the powerset, where is append the current element in list to the existing element in powerset.
This is why I thought I should use foldr twice in a nested way - one to go over all items in given list, and for each item I use foldr to go over all items in "result" (current powerset).
I faced the problem of the empty list (nothing is being added to the powerset), and thus added the "if" section (and not just foldr), but it doesn't work very well either.
I think that's it. I feel close but it is still very challenging, so every help will be welcomed.
Thanks!
The solution is simpler, there's no need to use a double foldr, try this:
(define (powerset-fr lst)
(foldr (lambda (e acc)
(append (map (lambda (x) (cons e x))
acc)
acc))
'(())
lst))
If your interpreter defines append-map or something equivalent, then the solution is a bit shorter - the results will be in a different order, but it doesn't matter:
(define (powerset-fr lst)
(foldr (lambda (e acc)
(append-map (lambda (x) (list x (cons e x)))
acc))
'(())
lst))
Either way, it works as expected:
(powerset-fr '(1 2 3))
=> '((1 2 3) (1 2) (1 3) (1) (2 3) (2) (3) ())

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.

Scheme - How do I get each list in a list that's not made up of more lists

(define (walk-list lst fun) ;;walk-list(list, fun)
(if (not(null? lst)) ;;IF the list isn't NULL
(begin
(if (list? lst) ;;&& the list is actually a list , THEN{
(begin
(if (equal? (car lst) '()) ;;IF the first element in the list is empty
(fun lst) ;;THEN call the function on the list (funct is supose to get each word)
(if (not (null? lst)) ;;ELSE IF the first item isn't a list
(begin ;;{
(walk-list (car lst) fun) ;;walk-list((car lst),fun)
(walk-list (cdr lst) fun))))))))) ;;walk-list((cdr lst),fun)
(walk-list test-document display) ;;walk through the list with the given document
The will look something like this:
(define test-document '(
((h e l l o));;paragraph1
((t h i s)(i s)(t e s t));;paragraph2
))
I'm trying to get each individual word into the document have a function applied to it. Where is says (fun list). But the function is never called.
First off. begin is if you need to do more than one expression. The first expression then needs to have side effects or else it's just a waste of processing power.
Ie.
(begin
(display "hello") ; display is a side effect
(something-else))
When you don't have more than one expression begin isn't needed. if has 3 parts. They are:
(if predicate-expression ; turnas into something true or #f (the only false value)
consequent-expression ; when predicate-expression evalautes to anything but #f
alternative-expression) ; when predicate-expression evaluates to #f this is done
You should ident your code properly. Here is the code idented with DrRacket IDE, with reduncant begin removed and missing alternative-expressions added so you see where they return:
(define (walk-list lst fun) ;;walk-list(list, fun)
(if (not (null? lst)) ;;IF the list isn't NULL
(if (list? lst) ;; && the list is actually a list , THEN{
(if (equal? (car lst) '()) ;; IF the first element in the list is empty
(fun lst) ;; THEN call the function on the list (funct is supose to get each word)
(if (not (null? lst)) ;; ELSE IF the first item isn't a list
(begin ;; Here begin is needed
(walk-list (car lst) fun) ;; walk-list((car lst),fun)
(walk-list (cdr lst) fun)) ;; walk-list((cdr lst),fun)
'undfined-return-1)) ;; stop recursion, return undefined value
'undefined-return-2) ;; stop recursion, return undefined value
'undefined-return-3)) ;; stop recursion, return undefined value
So when does (fun lst) get called? Never! There is no () in any car in (((h e l l o))((t h i s) (i s) (t e s t))) and (equal? (car lst) '()) which is (null? (car lst)) will always be #f. Since we know (not (null? lst)) is #t so it will walk car and cdr where either 'undefined-return-2 or 'undefined-return-3 will be evaluated and the procedure stops when everything is visited and nothing processed.
You haven't shown what (walk-list test-document display) should have displayed but I make a wild guess that you want it for every element except pairs and null, thus I would have written this like this:
(accumulate-tree test-document display (lambda (a d) 'return) '())
accumulate-tree you'll find in this SICP handout. It demonstrates many uses for it as well. For completeness I'll supply it here:
(define (accumulate-tree tree term combiner null-value)
(cond ((null? tree) null-value)
((not (pair? tree)) (term tree))
(else (combiner
(accumulate-tree (car tree)
term
combiner
null-value)
(accumulate-tree (cdr tree)
term
combiner
null-value)))))
Judging from you code you are an Algol programmer learning your first Lisp. I advice you to look at the SICP videoes and book.

recursive function accepts list in scheme

I'm new to Scheme and this is my very first Functional language. Implementing almost everything recursively seems to be awkward for me. Nevertheless, was able to implement functions of Factorial and Fibonacci problems having a single integer input.
However, what about when your function has an input of a list? Suppose this exercise:
FUNCTION: ret10 - extracts and returns as a list all the numbers greater than 10
that are found in a given list, guile> (ret10 ‘(x e (h n) 1 23 12 o))
OUTPUT: (23 12)
Should I have (define c(list)) as the argument of my function in this? or is there any other way?
Please help. Thanks!
Here's my derived solution based on sir Óscar López's answer below.. hope this helps others:
(define (ret10 lst)
(cond
((null? lst) '())
((and (number? (car lst)) (> (car lst) 10))
(cons (car lst)
(ret10 (cdr lst))))
(else (ret10 (cdr lst)))
)
)
This kind of problem where you receive a list as input and return another list as output has a well-known template for a solution. I'd start by recommending you take a look at The Little Schemer or How to Design Programs, either book will teach you the correct way to start thinking about the solution.
First, I'll show you how to solve a similar problem: copying a list, exactly as it comes. That'll demonstrate the general structure of the solution:
(define (copy lst)
(cond ((null? lst) ; if the input list is empty
'()) ; then return the empty list
(else ; otherwise create a new list
(cons (car lst) ; `cons` the first element
(copy (cdr lst)))))) ; and advance recursion over rest of list
Now let's see how the above relates to your problem. Clearly, the base case for the recursion will be the same. What's different is that we cons the first element with the rest of the list only if it's a number (hint: use the number? procedure) and it's greater than 10. If the condition doesn't hold, we just advance the recursion, without consing anything. Here's the general idea, fill-in the blanks:
(define (ret10 lst)
(cond (<???> <???>) ; base case: empty list
(<???> ; if the condition holds
(cons <???> ; `cons` first element
(ret10 <???>))) ; and advance recursion
(else ; otherwise
(ret10 <???>)))) ; simply advance recursion
Don't forget to test it:
(ret10 '(x e (h n) 1 23 12 o))
=> '(23 12)
As a final note: normally you'd solve this problem using the filter procedure - which takes as input a list and returns as output another list with only the elements that satisfy a given predicate. After you learn and understand how to write a solution "by hand", take a look at filter and write the solution using it, just to compare different approaches.
Solve the problem for the first element of the list and the recurse on rest of the list. Make sure you handle the termination condition (list is null?) and combine results (cons or append in the following)
(define (extract pred? list)
(if (null? list)
'()
(let ((head (car list))
(rest (cdr list)))
(cond ((pred? head) (cons head (extract pred? rest)))
((list? head) (append (extract pred? head)
(extract pred? rest)))
(else (extract pred? rest))))))
(define (ret10 list)
(extract (lambda (x) (and (number? x) (> x 10))) list))
> (ret10 '(0 11 (12 2) 13 3))
(11 12 13)

Scheme getting last element in list

Im trying to write a simple scheme function that returns the last element of a list. My function looks like it should work, but I managed to fail on something:
(define (last_element l)(
(cond (null? (cdr l)) (car l))
(last_element (cdr l))
))
(last_element '(1 2 3)) should return 3
DrRacket keeps on giving me the errors:
mcdr: contract violation
expected: mpair?
given: ()
Since (null? '()) is true, I don't get why this doesn't work.
This is a function I think I will need for a homework assignment (writing the function last-element is not the assignment), and the instructions say that I cannot use the built-in function reverse, so I can't just do (car (reverse l))
How do I fix this function?
Your syntax is totally wrong. You have an extra set of parentheses around the body of the function, not enough around the cond clauses, and your recursive case isn't even within the cond, so it gets done whether the test succeeds or fails. The following procedure should work:
(define (last_element l)
(cond ((null? (cdr l)) (car l))
(else (last_element (cdr l)))))
Just to add: in professional-level Racket, the last function is a part of the racket/list library.
you can retrieve the last element of a list by calling
(define (lastElem list) (car (reverse list)))
or, recursively using if built-in
(define (last list)
(if (zero? (length (cdr list)))
(car list)
(last (cdr list))))
You can also do it like this.First find the lenght of a list by cdring it down.Then use list-ref x which gives the x element of the list.
For example list-ref yourlistsname 0 gives the first element (basically car of the list.)And (list-ref
yourlistsname (- length 1)) gives the last element of the list.

Resources