Scheme - Inserting a number in a List - scheme

I have this code :
(define (Insert value list)
(if (null? list) (list value))
(if (< value (car list)) (list (Insert (value list))))
(Insert (cdr list) list))
I want this code to take a list (assuming it's in low to increasing order of integers) and insert a number in the correct place. This code does not work but I don't know why. Anyone know?

You have a bunch of errors. First, let's see how you can fix your implementation:
(define (insert value lst)
(cond ((null? lst) ; if the list is empty
(list value)) ; then return a single-element list
((<= value (car lst)) ; if current element >= value
(cons value lst)) ; insert value in current position
(else ; otherwise keep building the list
(cons (car lst) ; by adding current element
(insert value (cdr lst)))))) ; and advancing recursion
Now, let's see what went wrong with your code:
You must not name a parameter list, that clashes with the built-in procedure of the same name - one you're actually using! it's clear that they'll conflict
The conditionals are incorrectly structured, if you have multiple conditions use a cond expression. Notice that the values of the first two ifs are discarded, because they're not nested (inside a procedure, only the value of the last expression is returned). Some Scheme interpreters will even raise an error when you write ifs without the corresponding else part
In the second condition, you must stop the recursion by consing the value with the rest of the list. It's better to stop as soon as possible, when element >= value, in case there are repeated elements
In the last condition, you're passing the parameters in the wrong order, and forgot about the value
Also in the last condition, you forgot to cons the current element

You have several errors in your code. First, in Scheme it is more natural to include else clauses for ifs. Also, you had wrong the last if. Here is a version of your code with minor modifications:
(define (Insert value lst)
(if (null? lst) (list value)
(if (< value (car lst))
(cons value lst)
(cons (car lst) (Insert value (cdr lst))))))
Note that you have to provide actions for when the value is less than the head of the list and when it is not, and you have to construct the returning value using cons.

Related

Need help in scheme program won't know how to create it

Write a Scheme function that takes two atoms and a list as parameters and returns a list identical to the parameter list except all occurrences of the first given atom in the list are replaced with the second given atom.
(define(swap val1 val2 lst)
(cond ((null? lst) (lst val1))
((equal? val2 lst) (lst))
(else(equal? val2 (cadr lst)) (swap val1 val2 (cadr lst)))))
Two major syntactical problems is that (lst val1) and (lst) tries to call lst as a function, and that else shouldn't have a condition - the cond form is
(cond (condition1 expression1)
(condition2 expression2)
(else expression))
(equal? val2 lst) says "val2 is equal to the entire list lst". This does not make sense.
(equal? val2 (cadr lst)) says "val2 is equal to the second element of the list lst". You don't need to care about the second element.
The first element is car. The tail is cdr. (Many use first and rest, which are more modern names.)
You're pretty close to a solution, so I'll just give you a structure:
If the list is empty, the result is the empty list.
If the first element of the list is the one you're replacing, cons the new value onto the result of recursing on the rest of the list.
Otherwise, cons the existing value onto the result of recursing on the rest of the list.

How do I check my list to see if it contains only one value or more than one?

Here's what I have so far:
(DEFINE (swap lst)
(COND ((NULL? lst) lst)
(IF (lst --------))
))
I'm new to Scheme so I'm a little bit confused right now. For this function I'm supposed to check for a few things:
Is the list empty? If so, print out the unchanged empty list.
Is the list a single atom (element)? If so, print out the unchanged list.
If the list is not empty and has more than one atom, count out pairs and swap
the orders of those pairs.
i.e. If my list is (a b c d e f g)
then my function should return (b a d c f e g)
My primary question is how I go about checking my list to see if it has a single value or more than one.
Checking if a list has no elements is simple:
(null? lst)
Now, how can we verify if it has a single element? it's very similar to the previous case, we just check to see if the element after the current is the empty list:
(null? (cdr lst))
After that, the solution to the problem is obtained from the definition:
(define (swap lst)
(cond ((null? lst) lst)
((null? (cdr lst)) lst)
(else <do your thing>)))
For the last case, take care of consing the second element, to the first element, to the result of recursively processing the rest of the list; also remember that in this case for obtaining the "rest" we must advance over two elements at a time.

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) ())

Remove element off list

Someone tell me what is wrong with this code. I thought I mastered a few scheme skills to solve a friend's problem but it ended up messing my head. I am trying to remove all similar elements off the list. Earlier it was removing only the first element I want to remove, but now its removing the car and the first element f what I want to remove. I am looking for an output like: (delete 3 (list 2 3 4 3 5 3)), returns (2 4 5).
(define (delete n lst)
(cond
((null? lst) null)
((equal? n (car lst)) (cdr lst))
(else
(remove n (cdr lst)))))
It's because of this conditional:
((equal? n (car lst)) (cdr lst))
What this line does is it checks that n is the same as the first element in the list. If it is, it returns the rest of the list. Since your target element is the second element of the list, it returns the rest of the list, from the third element onward. Your first element in the list is completely dropped. You're not keeping track of the OK elements you've checked so far.
From your code, it looks like you want to loop through the elements of the list and, if you find your target value, call remove. If you want to implement it in this fashion, you need to also track the values that you've checked and verified that are not your target value. So your function needs to take three parameters: n, your target; lst the remaining numbers to check; and clean (or whatever you want to call it) that holds the already checked numbers.
This is a working version of your algorithm:
(define (delete n lst clean)
(cond
((empty? lst) clean)
((equal? n (car lst)) (delete n (cdr lst) clean))
(else
(delete n (cdr lst) (append clean (list (car lst)))))))
You'd call it like so: (delete 3 (list 2 3 4 3 5 3) '())
First it checks if you have numbers left to check. If you don't, it returns your clean list.
Then it checks to see if the first element matches your target element. If it does, then it calls delete again, effectively dropping the first element in the lst (notice it does not append it to the list of clean numbers).
The else, which is reached if the first element is not the target number, appends the first value of lst to the end of clean and calls delete again.
(Note that this code uses tail recursion, which is a way of writing recursive methods that track the intermediate values with each recursive call, as opposed to "regular" recursion that does the calculation at the end. Samrat's answer, below, is a regular recursive solution. A discussion of the tail recursion can be found here.)
From your post, it sounds like you want to remove all instances of the target number. Instead of using the remove function -- which only removes the first instance of the target number -- you should look at using the remove* function, which removes all instances. This would greatly simplify your function. So to remove all instances of 3 from your list, this would suffice:
(remove* '(3) (list 2 3 4 3 5 3))
If you wanted to wrap it in a function:
(define (delete n lst)
(remove* (list n) lst))
You should read up on map functions in general, since they pretty much do what you're looking for. (They apply a procedure against all elements in a list; The above could also be implemented with a filter-map if you had a more complicated procedure.)
Here's what I came up with:
(define (delete n lst)
(cond ((empty? lst) lst)
((= (car lst) n) (delete n (cdr lst)))
(else (append (list (car lst)) (delete n (cdr lst))))))

Find whether element in list integer?

I was wondering, how do you check if every element in a list is an integer or not? I can check the first element by using (integer? (car list), but if I do (integer? (cdr list), it always returns false (#f) because the whole of the last part of the list is not an integer as a group.
In this case let's say list is defined as.
(define list '(1 2 5 4 5 3))
(define get-integers
(lambda (x)
(if (null? x)
"All elements of list are integers"
(if (integer? (car x))
(get-integers (cdr x))
"Not all elements are an integer"))))
Practical Schemes provide functions for doing tests across whole sequences. An application of the andmap function, for example, would be appropriate. Racket provides a for/and to do something similar. If you really needed to write out the loop by hand, you'll be using recursion.
What you need to do is test each element in the list to see if it satisfies a condition (being an integer, in this case). When you evaluate (integer? (car list)) on a list of integers, you're checking if the first element in the list is an integer, and that's fine. But the expression (integer? (cdr list)) tests if a list is an integer (because cdr returns a list), and that won't work - you need to test the next element in the list, and the next, and so on until the list is empty.
There are several ways to do the above, the most straightforward would be to recur on the list testing each element in turn, returning false if a non-integer element was found or true if all the list was consumed without finding a non-integer element, like this:
(define (all-integers? lst)
(cond ((null? lst) #t)
((not (integer? (car lst))) #f)
(else (all-integers? (cdr lst)))))
A more practical approach would be to use a built-in procedure, like this:
(andmap integer? lst)
andmap will check if all the elements in lst evaluate to true for the given predicate. For example:
(andmap integer? '(1 2 3))
> #t
(andmap integer? '(1 "x" 3))
> #f
SRFI-1 uses the terms every and any rather than andmap and ormap. match can also be used:
(define list-of-integers?
(lambda (lst)
(match lst
(((? number?) ..1) #t)
(_ #f))))

Resources