Insert-everywhere procedure - scheme

I am trying to write a procedure that takes a a symbol and a list and inserts the symbol at every possible position inside the given list (thus generating a list of lists). I have coded the following definitions, which I must implement:
1
(define (insert-at pos elmt lst)
(if (empty? lst) (list elmt)
(if (= 1 pos)
(cons elmt lst)
(cons (first lst)
(insert-at (- pos 1) elmt (rest lst))))))
2
(define (generate-all-pos start end)
(if (= start end)
(list end)
(cons start (generate-all-pos (+ start 1) end))))
1 takes a position in a list (number), a symbol and the list itself and inserts the symbol at the requested position.
2 takes a start and a target position (numbers) and creates a sorted list with numbers from start to target.
So far I have got this:
(define (insert-everywhere sym los)
(cond
[(empty? los) (list sym)]
[else (cons (insert-at (first (generate-all-pos (first los)
(first (foldl cons empty los)))) sym los) (insert-everywhere sym (rest los)))
]
)
)
Which results in
> (insert-everywhere 'r '(1 2 3))
(list (list 'r 1 2 3) (list 2 'r 3) (list 3 'r) 'r)
so I actually managed to move the 'r' around. I'm kind of puzzled about preserving the preceding members of the list. Maybe I'm missing something very simple but I've stared and poked at the code for quite some time and this is the cleanest result I've had so far. Any help would be appreciated.

Óscar López's answer shows how you can do this in terms of the procedures that you've already defined. I'd like to point out a way to do this that recurses down the input list. It uses an auxiliary function called revappend (I've taken the name from Common Lisp's revappend). revappend takes a list and a tail, and efficiently returns the same thing that (append (reverse list) tail) would.
(define (revappend list tail)
(if (null? list)
tail
(revappend (rest list)
(list* (first list) tail))))
> (revappend '(3 2 1) '(4 5 6))
'(1 2 3 4 5 6)
The reason that we're interested in such a function is that as we recurse down the input list, we can build up a list of the elements we've already seen, but it's in reverse order. That is, as we walk down (1 2 3 4 5), it's easy to have:
rhead tail (revappend rhead (list* item tail))
----------- ----------- -----------------------------------
() (1 2 3 4 5) (r 1 2 3 4 5)
(1) (2 3 4 5) (1 r 2 3 4 5)
(2 1) (3 4 5) (1 2 r 3 4 5)
(3 2 1) (4 5) (1 2 3 r 4 5)
(4 3 2 1) (5) (1 2 3 4 r 5)
(5 4 3 2 1) () (1 2 3 4 5 r)
In each of these cases, (revappend rhead (list* item tail)) returns a list with item inserted in one of the positions. Thus, we can define insert-everywhere in terms of rhead and tail, and revappend, if we build up the results list in reverse order, and reverse it at the end of the loop.
(define (insert-everywhere item list)
(let ie ((tail list)
(rhead '())
(results '()))
(if (null? tail)
(reverse (list* (revappend rhead (list* item tail)) results))
(ie (rest tail)
(list* (first tail) rhead)
(list* (revappend rhead (list* item tail)) results)))))
(insert-everywhere 'r '(1 2 3))
;=> '((r 1 2 3) (1 r 2 3) (1 2 r 3) (1 2 3 r))
What's interesting about this is that the sublists all share the same tail structure. That is, the sublists share the structure as indicated in the following “diagram.”
;=> '((r 1 2 3) (1 r 2 3) (1 2 r 3) (1 2 3 r))
; ----- +++ o
; +++ o
; o

The insert-everywhere procedure is overly complicated, a simple map will do the trick. Try this:
(define (insert-everywhere sym los)
(map (lambda (i)
(insert-at i sym los))
(generate-all-pos 1 (add1 (length los)))))
Also notice that in Racket there exists a procedure called range, so you don't need to implement your own generate-all-pos:
(define (insert-everywhere sym los)
(map (lambda (i)
(insert-at i sym los))
(range 1 (+ 2 (length los)))))
Either way, it works as expected:
(insert-everywhere 'r '(1 2 3))
=> '((r 1 2 3) (1 r 2 3) (1 2 r 3) (1 2 3 r))

Related

How can I use dynamic programming in Scheme to solve the Coin Change problem?

I'm trying to learn a Lisp language and have settled on Guile and am trying to solve this problem:
You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.
Fundamentally, I understand the basic of dynamic programming where you can use recursion and memoization in order to save calculating at lower depths, but as Lisp I would expect it to be perfect for this type of problem. The problem I am having is returning separate lists for each combination of coins.
For an example case, consider target of 6 with coins [2, 3]. The simple tree would look like this:
The correct answer would be (3 3) with the other "complete" solution being (2 2 2).
However, if I try and construct these, the form I would want to use (without memoization) would look something like this.
(define get-coins (lambda (coins target)
(cond
((= target 0) '())
; not quite sure how to "terminate" a list here
; An idea is to return (list -1) and then filter
; lists that contain -1
((< target 0) ?????)
(else
; for each coin, recurse
(map (lambda (v)
(cons v (get-coins coins (- target v))))))
)
))
However, this doesn't return more lists as it goes through. Rather, it creates nested lists. And this is my problem. Any help with this would be greatly appreciated.
I wanted to avoid nested lists, so I used a variable results:
(define (get-coins coins target)
(let ((results '()))
Then I defined the function get-coins-helper, similar to your get-coins. And whenever I found some possible result, I used set! to update results:
(letrec ((get-coins-helper
(lambda (coins target result)
(cond ((= target 0) (set! results (cons result results)))
((< target 0) '())
(else (map (lambda (value)
(get-coins-helper coins
(- target value)
(cons value result)))
coins))))))
Then I called (get-coins-helper coins target '()) to find all possible results and at the end, I checked the value of results and returned -1 (if results are empty) or the shortest element of results:
(if (null? results)
-1
(car (sort results (lambda (x y) (< (length x)
(length y))))))
Full code:
(define (get-coins coins target)
(let ((results '()))
(letrec ((get-coins-helper
(lambda (coins target result)
(cond ((= target 0) (set! results (cons result results)))
((< target 0) '())
(else (map (lambda (value)
(get-coins-helper coins
(- target value)
(cons value result)))
coins))))))
(get-coins-helper coins target '())
(if (null? results)
-1
(car (sort results (lambda (x y) (< (length x)
(length y)))))))))
Some tests:
> (get-coins '(2 3) 6)
'(3 3)
> (get-coins '(2 3) 1)
-1
Using fold to choose best solutions. The result is a list whose car is the number of coins and cdr is the list of chosen coins. In the event that no solutions are feasible, (+inf.0) is returned.
(use-modules (srfi srfi-1))
(define (get-coins coins target)
(fold (lambda (coin best)
(let [(target (- target coin))]
(cond [(zero? target)
(list 1 coin)]
[(positive? target)
(let* [(res (get-coins coins target))
(score' (1+ (car res)))]
(if (< score' (car best))
(cons score' (cons coin (cdr res)))
best))]
[(negative? target)
best])))
(list +inf.0)
coins))
(get-coins (list 2) 6)
$8 = (3 2 2 2)
(get-coins (list 2 3) 6)
$9 = (2 3 3)
(get-coins (list 9) 6)
$10 = (+inf.0)
If you read the question carefully, all you need to keep track of is the number of coins needed to reach the target amount. You don't have generate every possible combination of coins to reach the target, just the one that minimizes the number of coins. And you don't even have to remember what that particular combination is, just its length. This simplifies things a bit since there's no need to build any lists.
For each denomination of coin that can possibly be used to reach the goal (So no coins bigger than the difference between the goal and the current sum), get the counts for using one of them and for using none of them, and return the minimum (Or -1 if no options present themselves).
(define (get-coins coins target)
(calculate-coins coins 0 0 target))
;; Do all the work in a helper function
(define (calculate-coins coins coin-count amount target)
(cond
((= amount target) coin-count) ; Success
((null? coins) -1) ; Failure
((> (car coins) (- target amount)) ; Current coin denomination is too big; skip it
(calculate-coins (cdr coins) coin-count amount target))
(else
;; Cases to consider:
;; Adding one of the current coin to the total and leaving open using more
;; Not using any of the current coins
(let ((with-first
(calculate-coins coins (+ coin-count 1) (+ amount (car coins)) target))
(without-first
(calculate-coins (cdr coins) coin-count amount target)))
(cond
((= with-first -1) without-first)
((= without-first -1) with-first)
(else (min with-first without-first)))))))
If you do want to get every possible combination of coin, one way is to, for each list of combinations that use a given coin, use append to combine it with a list of previous ways:
(use-modules (srfi srfi-1))
(define (get-coins2 coins target)
(define (helper target) ; This time define a nested helper function
(fold
(lambda (coin ways)
(cond
((= coin target) (cons (list coin) ways))
((< coin target)
(append
(map (lambda (c) (cons coin c))
(helper (- target coin)))
ways))
(else ways)))
'()
coins))
(let* ((ways (helper target))
(table (make-hash-table (length ways))))
;; Store each combination as a key in a hash table to remove duplicates
(for-each (lambda (way) (hash-set! table (sort-list way <) #t)) ways)
(hash-map->list (lambda (k v) k) table)))
Examples:
scheme#(guile-user)> (load "coins.scm")
scheme#(guile-user)> (get-coins '(2) 6)
$1 = 3
scheme#(guile-user)> (get-coins2 '(2) 6)
$2 = ((2 2 2))
scheme#(guile-user)> (get-coins '(2 3) 6)
$3 = 2
scheme#(guile-user)> (get-coins2 '(2 3) 6)
$4 = ((2 2 2) (3 3))
scheme#(guile-user)> (get-coins '(9) 6)
$5 = -1
scheme#(guile-user)> (get-coins2 '(9) 6)
$6 = ()
scheme#(guile-user)> (get-coins2 '(2 3) 12)
$7 = ((3 3 3 3) (2 2 2 3 3) (2 2 2 2 2 2))
scheme#(guile-user)> (get-coins '(5 2 3 4) 21)
$8 = 5
scheme#(guile-user)> (get-coins2 '(5 2 3 4) 21)
$9 = ((2 2 2 5 5 5) (2 3 3 4 4 5) (2 4 5 5 5) (3 3 3 4 4 4) (2 2 3 4 5 5) (4 4 4 4 5) (2 2 4 4 4 5) (2 2 3 3 3 4 4) (2 2 2 2 2 3 4 4) (2 2 2 2 4 4 5) (3 3 3 3 4 5) (2 2 2 2 3 3 3 4) (2 2 2 2 2 2 2 3 4) (2 2 2 2 2 2 4 5) (3 3 3 3 3 3 3) (2 2 3 3 3 3 5) (2 2 2 2 2 2 3 3 3) (2 2 2 2 2 3 3 5) (3 3 5 5 5) (2 2 2 2 2 2 2 2 2 3) (2 2 2 2 3 5 5) (2 2 2 2 2 2 2 2 5) (2 3 4 4 4 4) (2 2 2 3 4 4 4) (2 3 3 3 3 3 4) (2 2 2 3 3 4 5) (2 2 2 3 3 3 3 3) (2 3 3 3 5 5) (3 4 4 5 5))
scheme#(guile-user)> (filter (lambda (way) (= (length way) 5)) (get-coins2 '(5 2 3 4) 21))
$10 = ((2 4 5 5 5) (4 4 4 4 5) (3 3 5 5 5) (3 4 4 5 5))
There are many ways to do it, here is a brute-force solution. It is not elegant but it is simple.
(define mk/pairs
(lambda (sum coin/list)
((lambda (s) (s s
(map (lambda (x) (iota (+ 1 (quotient sum x)))) coin/list)
(lambda (s) s) ))
(lambda (s l* ret)
(if (null? l*)
(ret '(()))
(s s (cdr l*)
(lambda (r)
(ret (apply
append
(map (lambda (x) (map (lambda (y) (cons y x)) (car l*)))
r))))))))))
(define cost
(lambda (s pair coin/list)
(let ((sum (apply + (map * pair coin/list))))
(and (= s sum) pair))))
(define solve
(lambda (sum coin/list)
(let ((pairs (mk/pairs sum coin/list)))
(let ((solutions
(sort (filter (lambda (x) x)
(map (lambda (p) (cost sum p coin/list)) pairs))
(lambda (p1 p2)
(< (apply + p1)
(apply + p2))))))
(if (null? solutions)
"fail"
(car solutions))))))
A test looks like so:
% mit-scheme < coins.scm
MIT/GNU Scheme running under GNU/Linux
1 ]=> (solve 8 '(2 3 1))
;Value: (1 2 0)
1 ]=> (solve 6 '(2 3))
;Value: (0 2)
meaning that you have 1 coin of 2 and 2 coins of 3 in the first example and 2 coins of 3 in the second example.
I have used standard R6RS, so you should be able to convert it directly from mit/scheme to guile.

Looking for clarification on 'map' in Racket

new to stackoverflow and new to racket. I've been studying racket using this documentation: https://docs.racket-lang.org/reference/pairs.html
This is my understanding of map:
(map (lambda (number) (+ 1 number))'(1 2 3 4))
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
but when I see things like:
(define (matrix_addition matrix_a matrix_b)
(map (lambda (x y) (map + x y)) matrix_a matrix_b))
I get very lost. I assume we're assigning two variables x and y, then performing (map + x y),but I don't understand what or how (map + x y) works.
Another one I'm having trouble with is
(define (matrix_transpose matrix_a)
(apply map (lambda x x) matrix_a))
what does (lambda x x) exactly do?
Thank you so much for clarifying. As you can see I've been working on matrix operations as suggested by a friend of mine.
Here is one way to think about map:
(map f (list 1 2 3))
; computes
(list (f 1) (f 2) (f 3))
and
(map f (list 1 2 3) (list 11 22 33))
; computes
(list (f 1 11) (f 2 22) (f 3 33))
So your example with + becomes:
(map + (list 1 2 3) (list 11 22 33))
; computes
(list (+ 1 11) (+ 2 22) (+ 3 33))
which is (list 12 24 36).
In the beginning it with be clearer to write
(define f (lambda (x y) (+ x y)))
(map f (list 1 2 3) (list 11 22 33)))
but when you can get used to map and lambda, the shorthand
(map (lambda (x y) (+ x y)) (list 1 2 3) (list 11 22 33)))
is useful.
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
No, that's not what it does. map is a looping function, it calls the function separately for each element in the list, and returns a list of the results.
So first it binds number to 1 and performs (+ 1 number), which is (+ 1 1). Then it binds number to 2 and performs (+ 1 number), which is (+ 1 2). And so on. All the results are collected into a list, so it returns (2 3 4 5).
Getting to your matrix operation, the matrix is represented as a list of lists, so we need nested loops, which are done using nested calls to map.
(map (lambda (x y) (map + x y)) matrix_a matrix_b)
The outer map works as follows: First it binds x and y to the first elements of matrix_a and matrix_b respectively, and performs (map + x y). Then it binds x and y to the second elements of matrix_a and matrix_b, and performs (map + x y). And so on for each element of the two lists. Finally it returns a list of all these results.
The inner (map + x y) adds the corresponding elements of the two lists, returning a list of the sums. E.g. (map + '(1 2 3) '(4 5 6)) returns (5 7 9).
So all together this creates a list of lists, where each element is the sum of the corresponding elements of matrix_a and matrix_b.
Finally,
what does (lambda x x) exactly do?
It binds x to the list of all the arguments, and returns that list. So ((lambda x x) 1 2 3 4) returns the list (1 2 3 4). It's basically the inverse of apply, which spreads a list into multiple arguments to a function.
(apply (lambda x x) some-list)
returns a copy of some-list.
this assigns '(1 2 3 4) to variable number ,then map performs (+ 1 '(1 2 3 4)).
If it was that simple why the need for map. You could just do (+ 1 '(1 2 3 4)) directly. Here is an implementation of map1 which is map that can only have one list argument:
(define (map1 fn lst)
(if (empty? lst)
empty
(cons (fn (first lst))
(map1 f (rest lst)))))
And what it does:
(map1 add1 '(1 2 3))
; ==> (cons (add1 1) (cons (add1 2) (cons (add1 3) empty)))
; same as (list (add1 1) (add1 2) (add1 3))
The real map accepts any number of list arguments and then expect the element function to take as many elements that there are list arguments. eg.
(map (lambda (l n s) (list l n s)) '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
A very cool way to do this without knowing the number of elements is unzip
(define (unzip . lst)
(apply map list lst))
(unzip '(a b c) '(1 2 3) '($ % *))
; ==> ((a 1 $) (b 2 %) (c 3 *))
So apply flattens the call to (map list '(a b c) '(1 2 3) '($ % *)) and list takes arbitrary elements so it ends up working the same way as th eprevious example, but it will also work for other dimentions:
(unzip '(a b c d) '(1 2 3 4))
; ==> ((a 1) (b 2) (c 3) (d 4))
The first argument of map is a function. This function can require one or more arguments. Followed by the function in the arguments lists are one or more lists.
map loops from first to the last element of the lists in parallel.
And feeds therefore the i-th position of each list as arguments to the function
and collects the result into a results list which it returns.
Now three short examples which would make it clear to you how map goes through the lists:
(map list '(1 2 3))
;; => '((1) (2) (3))
(map list '(1 2 3) '(a b c))
;; => '((1 a) (2 b) (3 c))
(map list '(1 2 3) '(a b c) '(A B C))
;; => '((1 a A) (2 b B) (3 c C))

Creating an evaluate function in racket

Example of what function should do:
(list 3 4 6 9 7) ←→ 3x^4 + 4x^3 + 6x^2 + 9x + 7
What I have so far:
(define (poly-eval x numlist)
(compute-poly-tail x numlist 0 0))
(define (compute-poly-tail xn list n acc)
(cond
[(null? list) acc]
[else (compute-poly-tail (first list) (rest list)
(+ acc (* (first list) (expt xn n))) (+ n 1))]))
(check-expect(poly-eval 5 (list 1 0 -1)) 24)
(check-expect(poly-eval 0 (list 3 4 6 9 7)) 7)
(check-expect(poly-eval 2 (list 1 1 0 1 1 0)) 54)
Expected results:
(check-expect(poly-eval 5(list 1 0 -1)) 24)
(check-expect(poly-eval 0 (list 3 4 6 9 7))7)
(check-expect(poly-eval 2 (list 1 1 0 1 1 0)) 54)
I am getting a run-time error. Can someone spot what I am doing wrong. I don't know why I am getting these results.
There are a couple of errors in the code:
You need to process the coefficient's list in the correct order, corresponding to their position in the polynomial! you can either:
reverse the list from the beginning and process the coefficients from right to left (simpler).
Or start n in (sub1 (length numlist)) and decrease it at each iteration (that's what I did).
The order and value of the arguments when calling the recursion in compute-poly-tail is incorrect, check the procedure definition, make sure that you pass along the values in the same order as you defined them, also the first call to (first list) doesn't make any sense.
You should not name list a parameter, this will clash with the built-in procedure of the same name. I renamed it to lst.
This should fix the issues:
(define (poly-eval x numlist)
(compute-poly-tail x numlist (sub1 (length numlist)) 0))
(define (compute-poly-tail xn lst n acc)
(cond
[(null? lst) acc]
[else (compute-poly-tail xn
(rest lst)
(- n 1)
(+ acc (* (first lst) (expt xn n))))]))
It works as expected:
(poly-eval 5 (list 1 0 -1))
=> 24
(poly-eval 0 (list 3 4 6 9 7))
=> 7
(poly-eval 2 (list 1 1 0 1 1 0))
=> 54
Build power coefficient and unknown list than use map function.
; 2*3^1+4*3^0
; input is 3 and '(2 4)
; we need '(3 3) '(2 4) '(1 0)
; use map expt build '(3^1 3^0)
; use map * build '(2*3^1 4*3^0)
; use foldr + 0 sum up
(define (poly-eval x coefficient-ls)
(local ((define power-ls (reverse (build-list (length coefficient-ls) values)))
(define unknown-ls (build-list (length coefficient-ls) (λ (i) x))))
(foldr + 0 (map * coefficient-ls (map expt unknown-ls power-ls)))))

Scheme recursive

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

scheme - recursive function of lists

I have this program:
(define scale-tree
(lambda (tree factor)
(map (lambda (sub-tree)
(if (list? sub-tree)
(scale-tree sub-tree factor)
(* sub-tree factor)))
tree)))
(scale-tree (list 1 (list 2 (list 3 4) 5) (list 6 7))
10)
How does this code work? First, we give it the whole list as parameter (list 1 (list 2 (list 3 4) 5) (list 6 7)), and in the first call, the (lambda (sub-tree) gets the (list 1 (list 2 (list 3 4) 5) (list 6 7)) as parameter. For that, we call (scale-tree sub-tree factor) with (list 1 (list 2 (list 3 4) 5) (list 6 7)) again. When does the list reduce?
Thank you.
Remember what map does - it applies a function to every element of a list. So on the first call, this function:
(lambda (sub-tree)
(if (list? sub-tree)
(scale-tree sub-tree factor)
(* sub-tree factor)))
is being applied to the elements of your list: 1, (list 2 (list 3 4) 5), and (list 6 7). And so on in the recursive calls.

Resources