Remove duplication from the Scheme function - scheme

(define (merge-sorted lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1)
((>= (car lst1) (car lst2))
(cons (car lst2) (merge-sorted lst1 (cdr lst2))))
(else
(cons (car lst1) (merge-sorted (cdr lst1) lst2)))))
Output:
(merge-sorted '(1 3 4) '(2 4 5))
=> '(1 2 3 4 4 5)
I have to write function on lists in Scheme.
How can I fix the duplication?

Instead of having >= as one condition, you can test equality separately, whereby whenever (car lst1) is equal to (car lst2), you would keep one of them, but remove both on your recursive call by doing:
(cons (car lst1)
(merge-sorted (cdr lst1) (cdr lst2)))
For example:
(define (merge-sorted lst1 lst2)
(cond
((null? lst1) lst2)
((null? lst2) lst1)
((> (car lst1)
(car lst2))
(cons (car lst2)
(merge-sorted lst1 (cdr lst2))))
((< (car lst1)
(car lst2))
(cons (car lst1)
(merge-sorted (cdr lst1) lst2)))
(else
(cons (car lst1)
(merge-sorted (cdr lst1) (cdr lst2))))))
then you would have:
(merge-sorted '(1 3 4) '(2 4 5))
=> '(1 2 3 4 5)

Related

Scheme Problem: car: contract violation expected: pair? given: '()

I am stuck with this particular problem I was doing for fun:
Why does it cause a contract violation everytime car comes around? And are there any possible fixes?
(define (fv expr)
(cond ((eq? (car expr) 'lambda) (fv (cadr (cdr expr))))
((pair? (car expr)) (union (fv (car expr)) (fv (cdr expr))))
((symbol? (car expr)) (remove (car expr) (fv (cdr expr))))
(else '())))
(define (union set1 set2)
(cond ((null? set1) set2)
((member (car set1) set2) (union (cdr set1) set2))
(else (cons (car set1) (union (cdr set1) set2)))))
(define (remove item set)
(cond ((null? set) '())
((equal? item (car set)) (cdr set))
(else (cons (car set) (remove item (cdr set))))))
Input = (fv '(λ f (λ x (f ((t g) g)))))
Output =
car: contract violation expected: pair? given: '()
Output Should Be: (t g)
The error message:
car: contract violation expected: pair? given: '()
means that the function car was called with the argument '() (the empty list) and this gives an error.
Now you know that the problem is related to a call to car.
Since car is called multiple times in your program it is hard
to spot which car is the culprit. Presumably your Scheme implementation
displays a source locations that points to the offending expression.
But let's say you are not so lucky. In that case, you'll need to figure out which function has the problem. Inserting a few calls to display helps:
(define (fv expr)
(display (list 'fv: 'expr expr) (newline)
(cond ((eq? (car expr) 'lambda) (fv (cadr (cdr expr))))
((pair? (car expr)) (union (fv (car expr)) (fv (cdr expr))))
((symbol? (car expr)) (remove (car expr) (fv (cdr expr))))
(else '())))
(define (union set1 set2)
(display (list 'union: 'set1 set1 'set2 set2) (newline)
(cond ((null? set1) set2)
((member (car set1) set2) (union (cdr set1) set2))
(else (cons (car set1) (union (cdr set1) set2)))))
(define (remove item set)
(display (list 'remove: 'item item 'set set) (newline)
(cond ((null? set) '())
((equal? item (car set)) (cdr set))
(else (cons (car set) (remove item (cdr set))))))
If you try your example now, you'll see which function is called before the error occurs. In this case, I bet the problem is fv. Here car is called without a check that the argument is a non-empty list first.

How can i get the positive even elements in scheme

I am trying to get all the even and positive elements in scheme
I have the following code
(define (getVals lis)
(cond
((null? lis) lis)
(((> (car lis) 0) (even? (car lis)))
(cons (getVals (cdr lis))))
)
)
To check my code im using
getVals '(2 -2 4 6 5))
Which should output a new list with positive and even numbers (2 4 6)
Thank you
The simplest way would be to use built-in procedures:
(define (getVals lis)
(filter (lambda (x) (and (even? x) (positive? x)))
lis))
If you want to implement it from scratch, you need to fix your code:
It's missing the case where the current element does not meet the conditions (the else case).
It's missing one parameter when calling cons.
The condition is missing an and.
This is what I mean:
(define (getVals lis)
(cond
((null? lis) lis)
((and (even? (car lis)) (positive? (car lis)))
(cons (car lis) (getVals (cdr lis))))
(else (getVals (cdr lis)))))
Either way, it works as expected:
(getVals '(2 -2 4 6 5))
=> '(2 4 6)
And just to add to #OscarLopez's answer - if you have a second look you will see, that getVals is just the specific case of `filter.
(define (getVals lis)
(cond
((null? lis) lis)
((and (even? (car lis)) (positive? (car lis)))
(cons (car lis) (getVals (cdr lis))))
(else (getVals (cdr lis)))))
Versus:
(define (filter func lst)
(cond
((null? lis) lst)
((func (car lst))
(cons (car lst) (filter func (cdr lst))))
(else (filter func (cdr lst)))))
With filter func as getVales, and
with func as:
(lambda (x) (and (even? x) (positive? x)))
getVals is just a special case of filter:
(define (getVals lst)
(filter (lambda (x) (and (even? x) (positive? x))) lst))
But you should follow the style guide for Lisp languages -
don't use camelCase for function names but prefer the lisp-typic form get-vals.

Merge with no duplicates

I want to implement a merge function in scheme but with no duplicates, meaning when I have for example (merge '(1 2 8) '(2 5 6)) it should return '(1 2 5 6 8) and not
'(1 2 2 5 6 8). My current code returns the second result:
(define (merge lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1)
((>= (car lst1) (car lst2))
(cons (car lst2) (merge lst1 (cdr lst2))))
(else
(cons (car lst1) (merge (cdr lst1) lst2)))))
Add another clause to the cond statement to handle the case of equal elements separately:
> (define (merge lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1)
((> (car lst1) (car lst2))
(cons (car lst2) (merge lst1 (cdr lst2))))
((> (car lst2) (car lst1))
(cons (car lst1) (merge lst2 (cdr lst1))))
(else
(merge (cdr lst1) lst2))))
> (merge '(1 2 8) '(2 5 6))
(1 2 5 6 8)
Since you used the racket tag, I assume you have access to racket's functions. In that case, you can do this with set-union. The set-union function operates over generic sets, and a list satisfies the generic-set? interface. You could alternatively use append and remove-duplicates, but set-union takes care of that with one call.
If you also want the resulting list to be sorted, you can use sort, using < as your operator.
Composing all of these together you get:
(define (sorted-merge lst1 lst2)
(sort (set-union lst1 lst2) <))

Rotating a list to the right in scheme

if this is rotating a list to the left:
(define (rotate-left l)
(if (null? l)
'()
(append (cdr l) (cons(car l) '()))))
How would I rotate a list to the right?
If you're ok with writing a helper function to find the last element, it's pretty easy to do a recursive implementation:
(define rotate-right
(lambda (lis full)
(if (null? (cdr lis))
(cons (car lis) (get-all-but-last full))
(rotate-right (cdr lis) full))))
(define get-all-but-last
(lambda (lis)
(if (null? (cdr lis))
'()
(cons (car lis) (get-all-but-last (cdr lis))))))
Here is a short non-recursive solution:
(define (rotate-right l)
(let ((rev (reverse l)))
(cons (car rev) (reverse (cdr rev)))))
And here is a iterative solution:
(define (rotate-right l)
(let iter ((remain l)
(output '()))
(if (null? (cdr remain))
(cons (car remain) (reverse output))
(iter (cdr remain) (cons (car remain) output)))))
(rotate-right '(1 2 3 4 5)) ;==> (5 1 2 3 4)

How to make a union of 2 sets in scheme

(define (element-of-set x lst1)
(cond ((null? lst1) '())
((equal? x (car lst1)) (cons (car lst1) (element-of-set x (cdr lst1))))
(else
(element-of-set x (cdr lst1)))))
(define (helper set1 set2) (append set1 set2))
(define (union-set set1 set2)
(cond ((null? set1) '())
((> (length (element-of-set (car set1) (helper set1 set2))) 1) (cons (car set1) (union-set (cdr set1) (cdr set2))))
((> (length (element-of-set (car set2) (helper set1 set2))) 1) (cons (car set2) (union-set (cdr set1) (cdr set2))))
(else
(append (helper set1 set2) (union-set (cdr set1) (cdr set2))))))
This code is suppose to find the union of 2 sets. I tried to put the two sets together and then take out any repeats but it didn't work.
How about this:
#lang racket
(require racket/set)
(define (union-set set1 set2)
(set-union set1 set2))
(union-set '(1 2 3) '(4 3 2))
=> '(4 1 2 3)
FYI, set is a built-in data type in Racket, so it's easy to write a set union - just call the existing procedure! Anyway, if you want to roll your own version it's also easy, and simpler than your current implementation:
(define (element-of-set x lst1)
(cond ((null? lst1) #f)
((equal? x (car lst1)) #t)
(else (element-of-set x (cdr lst1)))))
(define (union-set set1 set2)
(cond ((null? set1) set2)
((element-of-set (car set1) set2)
(union-set (cdr set1) set2))
(else
(cons (car set1) (union-set (cdr set1) set2)))))
Here's how I'd do it in Common Lisp if it didn't include functions for set operations.
(defun set-union (set1 set2)
(remove-duplicates (append set1 set2)))
I'll write one in Scheme.

Resources