Scheme recursive - scheme

Deos anyone know, how I can make this funktion recursive by inserting the function somewhere? I am not allowed to use implemented functions for lists except append, make-pair(list) and reverse.
(: split-list ((list-of %a) -> (tuple-of (list-of %a) (list-of %a))))
(check-expect (split-list (list 1 2)) (make-tuple (list 1) (list 2)))
(check-expect (split-list (list 1 2 3 4)) (make-tuple (list 1 3) (list 2 4)))
(check-expect (split-list (list 1 2 3)) (make-tuple (list 1 3) (list 2)))
(check-expect (split-list (list 1 2 3 4 5)) (make-tuple (list 1 3 5) (list 2 4)))
(check-expect (split-list (list 1 2 3 4 5 6)) (make-tuple (list 1 3 5) (list 2 4 6)))
(define split-list
(lambda (x)
(match x
(empty empty)
((make-pair a empty) (make-tuple a empty))
((make-pair a (make-pair b empty)) (make-tuple (list a) (list b)))
((make-pair a (make-pair b c)) (make-tuple (list a (first c)) (list b (first(rest c))))))))
Code for make-tuple:
(define-record-procedures-parametric tuple tuple-of
make-tuple
tuple?
(first-tuple
rest-tuple))

Here's a way you can fix it using match and a named let, seen below as loop.
(define (split xs)
(let loop ((xs xs) ;; the list, initialized with our input
(l empty) ;; "left" accumulator, initialized with an empty list
(r empty)) ;; "right" accumulator, initialized with an empty list
(match xs
((list a b rest ...) ;; at least two elements
(loop rest
(cons a l)
(cons b r)))
((cons a empty) ;; one element
(loop empty
(cons a l)
r))
(else ;; zero elements
(list (reverse l)
(reverse r))))))
Above we use a loop to build up left and right lists then we use reverse to return the final answer. We can avoid having to reverse the answer if we build the answer in reverse order! The technique used here is called continuation passing style.
(define (split xs (then list))
(match xs
((list a b rest ...) ;; at least two elements
(split rest
(λ (l r)
(then (cons a l)
(cons b r)))))
((cons a empty) ;; only one element
(then (list a) empty))
(else ;; zero elements
(then empty empty))))
Both implementations perform to specification.
(split '())
;; => '(() ())
(split '(1))
;; => '((1) ())
(split '(1 2 3 4 5 6 7))
;; => '((1 3 5 7) (2 4 6))
Grouping the result in a list is an intuitive default, but it's probable that you plan to do something with the separate parts anyway
(define my-list '(1 2 3 4 5 6 7))
(let* ((result (split my-list)) ;; split the list into parts
(l (car result)) ;; get the "left" part
(r (cadr result))) ;; get the "right" part
(printf "odds: ~a, evens: ~a~n" l r))
;; odds: (1 3 5 7), evens: (2 4 6)
Above, continuation passing style gives us unique control over the returned result. The continuation is configurable at the call site, using a second parameter.
(split '(1 2 3 4 5 6 7) list) ;; same as default
;; '((1 3 5 7) (2 4 6))
(split '(1 2 3 4 5 6 7) cons)
;; '((1 3 5 7) 2 4 6)
(split '(1 2 3 4 5 6 7)
(λ (l r)
(printf "odds: ~a, evens: ~a~n" l r)))
;; odds: (1 3 5 7), evens: (2 4 6)
(split '(1 2 3 4 5 6 7)
(curry printf "odds: ~a, evens: ~a~n"))
;; odds: (1 3 5 7), evens: (2 4 6)
Oscar's answer using an auxiliary helper function or the first implementation in this post using loop are practical and idiomatic programs. Continuation passing style is a nice academic exercise, but I only demonstrated it here because it shows how to step around two complex tasks:
building up an output list without having to reverse it
returning multiple values

I don't have access to the definitions of make-pair and make-tuple that you're using. I can think of a recursive algorithm in terms of Scheme lists, it should be easy to adapt this to your requirements, just use make-tuple in place of list, make-pair in place of cons and make the necessary adjustments:
(define (split lst l1 l2)
(cond ((empty? lst) ; end of list with even number of elements
(list (reverse l1) (reverse l2))) ; return solution
((empty? (rest lst)) ; end of list with odd number of elements
(list (reverse (cons (first lst) l1)) (reverse l2))) ; return solution
(else ; advance two elements at a time, build two separate lists
(split (rest (rest lst)) (cons (first lst) l1) (cons (second lst) l2)))))
(define (split-list lst)
; call helper procedure with initial values
(split lst '() '()))
For example:
(split-list '(1 2))
=> '((1) (2))
(split-list '(1 2 3 4))
=> '((1 3) (2 4))
(split-list '(1 2 3))
=> '((1 3) (2))
(split-list '(1 2 3 4 5))
=> '((1 3 5) (2 4))
(split-list '(1 2 3 4 5 6))
=> '((1 3 5) (2 4 6))

split is kind of a de-interleave function. In many other languages, split names functions which create sublists/subsequences of a list/sequence which preserve the actual order. That is why I don't like to name this function split, because it changes the order of elements in some way.
Tail-call-rescursive solution
(define de-interleave (l (acc '(() ())))
(cond ((null? l) (map reverse acc)) ; reverse each inner list
((= (length l) 1)
(de-interleave '() (list (cons (first l) (first acc))
(second acc))))
(else
(de-interleave (cddr l) (list (cons (first l) (first acc))
(cons (second l) (second acc)))))))

You seem to be using the module deinprogramm/DMdA-vanilla.
The simplest way is to match the current state of the list and call it again with the rest:
(define split-list
(lambda (x)
(match x
;the result should always be a tuple
(empty (make-tuple empty empty))
((list a) (make-tuple (list a) empty))
((list a b) (make-tuple (list a) (list b)))
;call split-list with the remaining elements, then insert the first two elements to each list in the tuple
((make-pair a (make-pair b c))
((lambda (t)
(make-tuple (make-pair a (first-tuple t))
(make-pair b (rest-tuple t))))
(split-list c))))))

Related

Scheme append function workflow

Hello I am looking at the append function
(define ( append x y )
(if (null? x)
y)
(cons (car x)
(append (cdr x)
y))))
I understand how the list is generated but when the first list x is empty we directly return y,I don't see how we connect it to the first list "x".Does the process go like this (cons a1(cons a2....(cons an y).. )) and how does the program understand to plug in y at (cons an y),Is it because in the end the expression is (cons an-1 ,append (cdr x) y ) and the result of (append (cdr x ),y) is y?
Your function has an error in it such that is in parsing has one closing parens too much in the end. I thin kit's because you close if just after y. Because of that it will always do the last expression and it fails when x is empty.
The correct append looks like this:
(define (append x y)
(if (null? x)
y
(cons (car x)
(append (cdr x)
y))))
I like to explain recursive functions by simplest to general so we start off with the obvious, the base case:
(append '() '(3 4))
This will be #t for x being null? and the result is (3 4). Now lets try with a one element list as x:
(append '(2) '(3 4))
This is #f for x being `null? thus you can substitute it with:
(cons (car '(2))
(append (cdr '(2))
'(3 4)))
We can evaluate the accessors on '(2):
(cons 2 (append '() '(3 4))
Since we did the base case before we know the answer to the append part, which is '(3 4) so we end up with:
(cons 2 '(3 4)) ; ==> (2 3 4)
Lets do a new x:
(append '(1 2) '(3 4))
Here as the previous x is not null? so you substitute with the alternative again:
(cons (car '(1 2))
(append (cdr '(1 2))
'(3 4)))
As the previous time we can evaluate the accessors:
(cons 1
(append '(2)
'(3 4)))
Notice that again we have familiar arguments to append so we could just substitute that with our last result, however I take the step before so you see the pattern you noticed:
(cons 1 (cons 2 (append '() '(3 4)))) ; ==>
(cons 1 (cons 2 '(3 4))) ; ==>
(cons 1 '(2 3 4)) ; ==>
; ==> (1 2 3 4)
So if you have a 12 element x it gets 12 cons nested before hitting the base case and then it evaluates the the inner to the outer since list are always created from end to beginning since the functions need to evaluate their arguments before applying.

Racket Pass List Elements to a Function

I'm trying to figure out how I would be able to pass the values that I have within a list to a function.
Ex:
(define l (list (list 1) (list 2) (list 3 4))) --> l = '((1) (2) (3 4))
(define (myFunc el1 el2 el3)
...Whatever is in my function).
Thus, how would I be able to call myFunc with the elements in l,
I would have (myFunc '(1) '(2) '(3 4)).
Try using apply. For instance:
(define l (list (list 1) (list 2) (list 3 4)))
(define (my-func el1 el2 el3)
(+ (length el1) (length el2) (length el3)))
(apply my-func l) ; => 4
Here is the documentation.

Circular permutation in scheme

Hello I try to make circular permutations in Scheme (Dr. Racket) using recursion.
For example, if we have (1 2 3) a circular permutation gives ((1 2 3) (2 3 1) (3 1 2)).
I wrote a piece of code but I have a problem to make the shift.
My code:
(define cpermit
(lambda (lst)
(cpermitAux lst (length lst))))
(define cpermitAux
(lambda (lst n)
(if (zero? n) '()
(append (cpermitAux lst (- n 1)) (cons lst '())))))
Where (cpermit '(1 2 3)) gives '((1 2 3) (1 2 3) (1 2 3))
You can use function that shifts your list
(defun lshift (l) (append (cdr l) (list (car l))))
This will shift your list left.
Use this function before appendings
(define cpermit
(lambda (lst)
(cpermitAux lst (length lst))))
(define cpermitAux
(lambda (lst n)
(if (zero? n) '()
(append (cpermitAux (lshift lst) (- n 1)) (lshift (cons lst '()))))))
This answer is a series of translations of #rnso's code, modified to use a recursive helper function instead of repeated set!.
#lang racket
(define (cpermit sl)
;; n starts at (length sl) and goes towards zero
;; sl starts at sl
;; outl starts at '()
(define (loop n sl outl)
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))])) ; the new outl
(loop (length sl) sl '()))
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
For a shorthand for this kind of recursive helper, you can use a named let. This brings the initial values up to the top to make it easier to understand.
#lang racket
(define (cpermit sl)
(let loop ([n (length sl)] ; goes towards zero
[sl sl]
[outl '()])
(cond [(zero? n) outl]
[else
(loop (sub1 n) ; the new n
(append (rest sl) (list (first sl))) ; the new sl
(cons sl outl))]))) ; the new outl
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
To #rnso, you can think of the n, sl, and outl as fulfilling the same purpose as "mutable variables," but this is really the same code as I wrote before when I defined loop as a recursive helper function.
The patterns above are very common for accumulators in Scheme/Racket code. The (cond [(zero? n) ....] [else (loop (sub1 n) ....)]) is a little annoying to write out every time you want a loop like this. So instead you can use for/fold with two accumulators.
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
outl)
> (cpermit (list 1 2 3 4))
(list (list 4 1 2 3) (list 3 4 1 2) (list 2 3 4 1) (list 1 2 3 4))
You might have noticed that the outer list has the (list 1 2 3 4) last, the (list 2 3 4 1) second-to-last, etc. This is because we built the list back-to-front by pre-pending to it with cons. To fix this, we can just reverse it at the end.
#lang racket
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (append (rest sl) (list (first sl))) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
And finally, the (append (rest sl) (list (first sl))) deserves to be its own helper function, because it has a clear purpose: to rotate the list once around.
#lang racket
;; rotate-once : (Listof A) -> (Listof A)
;; rotates a list once around, sending the first element to the back
(define (rotate-once lst)
(append (rest lst) (list (first lst))))
(define (cpermit sl)
(define-values [_ outl]
(for/fold ([sl sl] [outl '()])
([i (length sl)])
(values (rotate-once sl) ; the new sl
(cons sl outl)))) ; the new outl
(reverse outl))
> (cpermit (list 1 2 3 4))
(list (list 1 2 3 4) (list 2 3 4 1) (list 3 4 1 2) (list 4 1 2 3))
Following code also works (without any helper function):
(define (cpermit sl)
(define outl '())
(for((i (length sl)))
(set! sl (append (rest sl) (list (first sl))) )
(set! outl (cons sl outl)))
outl)
(cpermit '(1 2 3 4))
Output is:
'((1 2 3 4) (4 1 2 3) (3 4 1 2) (2 3 4 1))
Following solution is functional and short. I find that in many cases, helper functions can be replaced by default arguments:
(define (cpermit_1 sl (outl '()) (len (length sl)))
(cond ((< len 1) outl)
(else (define sl2 (append (rest sl) (list (first sl))))
(cpermit_1 sl2 (cons sl2 outl) (sub1 len)))))
The output is:
(cpermit_1 '(1 2 3 4))
'((1 2 3 4) (4 1 2 3) (3 4 1 2) (2 3 4 1))

How to split a list into two parts in Scheme

Example: (split '(1 2 3 4) '3)
the Answer should be: ((1 2 3) 4)
The function required 1 list and 1 number, the output should be nested list
the nested list consist of all elements of "mylist" which are equal or less than the "num", and the greater number should be on the right of the list.
I tried but out put is only one list:
(define (split mylist num)
(cond
((null? mylist)'())
((list? (car mylist))(split(car mylist) num))
((> (car mylist) num)(split(cdr mylist) num))
(else(cons (car mylist) (split(cdr mylist) num)))))
A simple solution:
(define (split-list xs y)
(define (less x) (<= x y))
(define (greater x) (> x y))
(list (filter less xs)
(filter greater xs)))
An alternative:
(define (split-list xs y)
(define (less x) (<= x y))
(define-values (as bs) (partition less xs))
(list as bs))
(split-list '(1 2 3 4) 3)
Here's one possible solution, using built-in procedures in Racket:
(define (split mylist num)
(cons
(takef mylist (lambda (n) (<= n num)))
(dropf mylist (lambda (n) (<= n num)))))
For example:
(split '(1 2 3 4) 3)
=> '((1 2 3) 4)
(split '(1 2 3 4 5) 3)
=> '((1 2 3) 4 5)
This is roll your own version using named let. It makes one pass through the data and the result is in reverse order since it's the most effective.
(define (binary-bucket-sort lst threshold)
(let loop ((lst lst) (less-equal '()) (greater '()))
(cond ((null? lst)
(cons less-equal greater))
((<= (car lst) threshold)
(loop (cdr lst) (cons (car lst) less-equal) greater))
(else
(loop (cdr lst) less-equal (cons (car lst) greater))))))
(binary-bucket-sort '(1 5 9 2 6 10 3 7 9 8 4 0) 5)
; ==> ((0 4 3 2 5 1) . (8 9 7 10 6 9))
If you're comfortable with some of the more functional constructs in Racket, such as curry and the like, you can use this rather compact approach:
(define (split-list xs y)
(call-with-values (thunk (partition (curry >= y) xs)) cons))
> (split-list '(1 2 3 4 5 6 7) 3)
'((1 2 3) 4 5 6 7)

Output Elements in List That Are Not Incommon

I've created a function that should return the elements that the two lists do not have in common. Currently, they are outputting exactly what is passed into it. Any suggestions on how to fix this?
(define (findDifference lst1 lst2)
(if (null? lst1) lst2
(cons (car lst1) (findDifference (cdr lst1) lst2))))
(findDifference '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5))
Current Output: (2 3 4 (2 3) 2 (4 5) 2 4 (4 5))
Desired Output: (3 (2 3))
You're asking for the symmetric difference of two lists. Try this:
(define (diff list1 list2)
(union (complement list1 list2)
(complement list2 list1)))
Using the following helper procedures:
(define (union list1 list2)
(cond ((null? list1) list2)
((member (car list1) list2) (union (cdr list1) list2))
(else (cons (car list1) (union (cdr list1) list2)))))
(define (complement list1 list2)
(cond ((null? list1) '())
((member (car list1) list2) (complement (cdr list1) list2))
(else (cons (car list1) (complement (cdr list1) list2)))))
Also notice that if you're using Racket you can simply use the built-in set-symmetric-difference procedure for the same effect. For example:
(diff '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5)))
=> '(3 (2 3))
Since it seems like homework and I do not want to spoil the fun, here is the brute force algorithm, with some bits left out. If you are really stuck I will give you the full source.
(define (sym-diff xs ys)
;; Since we have the helper function we can determine all the elements that are in the first list,
;; but not in the second list.
;; Then we can pass this intermediate result to the second call to sym-diff-helper.
;;This will return us all the elements that are in the second list but not the first.
(let ((in-first-not-second ...))
(sym-diff-helper ys xs in-first-not-second)))
;; This function will return all the elements from the first list that are not in the second list!
(define (sym-diff-helper xs ys acc)
(cond
;; If the first list is empty we have checked it.
(...
acc)
;; If the first list is not empty yet, check if the first element
;; is in the second list.
;; If so, discard it and continue with the rest of the list.
((member ... ...)
(sym-diff-helper ... ... ...)
;; If the first element of the first list is not in the second list,
;; add it to the accumulator and continue with the rest of the list.
(else
(sym-diff-helper ... ... ...)))
(sym-diff-helper '(1 2 3) '(2 3 4) '())
;; == (1)
(sym-diff-helper '(1 2 (3 4) 5) '(2 3 4) '())
;; == (5 (3 4) 1)
(sym-diff '(2 3 4 (2 3) 2 (4 5)) '(2 4 (4 5)))
;; == ((2 3) 3)
Note that I have chosen to use member. There are a few other search functions but they were not well suited in this case. Hence, I left it there. More info on the search functions can be found here: http://docs.racket-lang.org/reference/pairs.html#%28part..List.Searching%29

Resources