Splitting list into lists of a maximal length - scheme

For instance
I want to make a list which has 20 numbers showed below. separate
(list 1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20)
into list of list which contains 10 numbers in each list. just like below
(list (list 1 2 3 4 5 6 7 8 9 10)
(list 11 12 13 14 15 16 17 18 19 20))
what is the best way to do this?
//Sorry for my poor English.

(define (take n xs)
(if (or (= n 0)
(null? xs) )
'()
(cons (car xs)
(take (- n 1)
(cdr xs) ))))
(define (drop n xs)
(if (or (= n 0)
(null? xs) )
xs
(drop (- n 1)
(cdr xs) )))
(define (split n xs)
(if (null? xs) '()
(cons (take n xs)
(split n (drop n xs)) )))
(display
(split 3 (list 1 2 3 4 5)) ) ; `((1 2 3) (4 5))`
Alternative split definition, elimination of wrapper recursion using named let:
(define (split n xs)
(let spl ((xs' xs)) ; Named let
(if (null? xs') '()
(cons (take n xs')
(spl (drop n xs')) ))))

Related

How to create a function that makes a list that contains 1,2,3,4,5... to n in Scheme

I am trying to learn Scheme, and I encounter a problem.
I am able to make a recursive function to create a list like (5,4,3,2,1). But I don't know how to create a function
(let's say (define (make_list n)) )
that has ascending order of elements likes (1,2,3,4,5....n).
Someone some hint?
(define (make_list n)
(if (= n 1)
(list 1)
(append (list n) (make_list (- n 1)))))
So this is how I make a list with n element, and it returns
> (make_list 3)
'(3 2 1)
> (make_list 5)
'(5 4 3 2 1)
What I need is to return something like:
> (make_list 3)
'(1 2 3)
> (make_list 5)
'(1 2 3 4 5)
You can make a list of ascending elements with the range function:
> (range 1 20)
'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
If you want to iterate over this list consider using in-range instead, which will generate the list items as needed, e.g.:
> (in-range 1 20)
#<stream>
> (for ([i (in-range 1 20)])
(displayln (* i 10)))
10
20
30
...
However usually the likes of map, filter and fold are better ways to handle iteration.
Read the documentation here:
https://docs.racket-lang.org/reference/pairs.html#%28def._%28%28lib._racket%2Flist..rkt%29._range%29%29
You should avoid using append where it is not necessary.
Append adds elements to the back of your list, for which it first needs to traverse the entire list to find the end. Cons does not need to do this, it can just add elements to the front immediately.
Both an ascending list and a descending one can be created using just cons.
(define (desc-list n)
(if (= n 1)
(list 1)
(cons n (desc-list (- n 1)))))
> (desc-list 5)
'(5 4 3 2 1)
(define (asc-list from to)
(if (> from to)
'()
(cons from (asc-list (+ from 1) to))))
> (asc-list 1 5)
'(1 2 3 4 5)
Though you could use append if you really want too.
All you have to do to get what you want then is reverse the parameters you pass to append.
(define (make_list n)
(if (= n 1)
(list 1)
(append (make_list (- n 1)) (list n))))
> (make_list 5)
'(1 2 3 4 5)
So you were very close.
Based on your current definition you have
(make-list 5) = (append (list 5) (make-list 4))
= { 5 } + { 4 ..... 1 }
but you want
(make-list 5) = { 1 ..... 4 } + { 5 }
= (append ... ...)
so to change the order of the result you just need to change the order in which you are creating the result.
Don't make a list one element a time with append. append appends two lists linear time so if you do that for each element in an argument you might make it quadratic time.
Lists are cons-ed from end to beginning. If you want to make a list 0..n you need to count downwards from n while you are accumulating, like this:
(define (make-list n)
(define (helper n acc)
(if (< n 0)
acc
(helper (- n 1) (cons n acc))))
(helper n '()))
Sometimes you cannot do that and then you usually would first make the list in reverse, then reverse it. that is two linear time operations making the end result linear too:
(define (sum lst1 lst2)
(let helper ((lst1 lst1) (lst2 lst2) (acc '()))
(if (null? lst1)
(reverse acc)
(helper (cdr lst1)
(cdr lst2)
(cons (+ (car lst1) (car lst2)) acc)))))
Just adding to this thread that srfi-1 contains the iota function
; (iota numElems [start] [step])
> (iota 10)
(0 1 2 3 4 5 6 7 8 9)
> (iota 10 0 2)
(0 2 4 6 8 10 12 14 16 18)
> (iota 10 10 1)
(10 11 12 13 14 15 16 17 18 19)
Think about using a sub-procedure. You could use your code as the sub-procedure and just reverse the result in the main procedure:
(define (make-list n)
(define (sub n)
(if (= n 1)
(list 1)
(append (list n) (sub (- n 1)))))
(reverse (sub n)))
Alternatively, and more efficiently, you can use an accumulator (called res in this example); it uses cons rather than append, and doesn't need an extra reverse step:
(define (make-list n)
(define (sub n res)
(if (< n 1)
res
(sub (- n 1) (cons n res))))
(sub n null))

Expanded form of fold in Racket

Example from http://www.cse.unsw.edu.au/~en1000/haskell/hof.html :
(foldr / 7 (list 34 56 12 4 23))
(foldl / 7 (list 34 56 12 4 23))
Output in Racket:
5 193/196
5 193/196
What would be the full (expanded) form of foldl and foldr in this case? It is not the following:
> (/ (/ (/ (/ (/ 7 34) 56) 12) 4) 23)
1/300288
Edit: I have modified above question since implementation of fold in Racket vs Haskell has been explained in another question Why is foldl defined in a strange way in Racket?.
Edit: If I understand the answers clearly, the expanded form can be shown very clearly using "threading" module, where statements appear in order of execution (_ indicates output of previous statement):
foldl:
(require threading)
; expanded form of (foldl / 7 (list 34 56 12 4 23))
; FROM LEFT TO RIGHT:
(~> 7
(/ 34 _)
(/ 56 _)
(/ 12 _)
(/ 4 _)
(/ 23 _) )
foldr:
; expanded form of (foldr / 7 (list 34 56 12 4 23))
; FROM RIGHT TO LEFT:
(~> 7
(/ 23 _)
(/ 4 _)
(/ 12 _)
(/ 56 _)
(/ 34 _) )
The output in both cases is same:
5 193/196
5 193/196
It gives correct answers (which are different for foldl and foldr) in following example also:
; FROM LEFT TO RIGHT:
(foldl - 0 '(1 2 3 4))
(~> 0
(- 1 _) ; 1-0=1
(- 2 _) ; 2-1=1
(- 3 _) ; 3-1=2
(- 4 _)) ; 4-2=2
; FROM RIGHT TO LEFT:
(foldr - 0 '(1 2 3 4))
(~> 0
(- 4 _) ; 4-0=4
(- 3 _) ; 3-4=-1
(- 2 _) ; 2-(-1)=3
(- 1 _)) ; 1-3=-2
Output:
2
2
-2
-2
In common language, it seems:
The sent function takes 2 arguments,
the first argument is from the list, one after the other
(left to right or right to left depending on foldl and foldr),
the second argument is init first and
then the output of previous calculation.
In DrRacket, press the right mouse button on foldl and choose "Open defining file" In the provide list right click again and choose "Jump to the next bound occurance". You'll see this:
(define foldl
(case-lambda
[(f init l)
(check-fold 'foldl f init l null)
(let loop ([init init] [l l])
(if (null? l) init (loop (f (car l) init) (cdr l))))]
[(f init l . ls)
(check-fold 'foldl f init l ls)
(let loop ([init init] [ls (cons l ls)])
(if (pair? (car ls)) ; `check-fold' ensures all lists have equal length
(loop (apply f (mapadd car ls init)) (map cdr ls))
init))]))
However since you only have one list it's the first term in case lambda that is the current and the fist line checks arguments and throw exceptions. You can simplify it to:
(define (foldl f init l)
(let loop ([init init] [l l])
(if (null? l)
init
(loop (f (car l) init) (cdr l))))
Using substitution rules:
(foldl / 7 '(34 56 12 4 23)) ;==>
(loop 7 '(34 56 12 4 23)) ;==>
(loop (/ (car '(34 56 12 4 23)) 7) (cdr '(34 56 12 4 23))) ;==>
(loop (/ (car '(56 12 4 23)) (/ (car '(34 56 12 4 23)) 7)) (cdr '(56 12 4 23))) ;==>
(loop (/ (car '(12 4 23)) (/ (car '(56 12 4 23)) (/ (car '(34 56 12 4 23)) 7))) (cdr '(12 4 23))) ;==>
(loop (/ (car '(4 23)) (/ (car '(12 4 23)) (/ (car '(56 12 4 23)) (/ (car '(34 56 12 4 23)) 7)))) (cdr '(4 23))) ;==>
(loop (/ (car '(23)) (/ (car '(4 23)) (/ (car '(12 4 23)) (/ (car '(56 12 4 23)) (/ (car '(34 56 12 4 23)) 7))))) (cdr '(23))) ;==>
(/ (car '(23)) (/ (car '(4 23)) (/ (car '(12 4 23)) (/ (car '(56 12 4 23)) (/ (car '(34 56 12 4 23)) 7))))) ;==>
(/ 23 (/ 4 (/ 12 (/ 56 (/ 34 7))))) ;==>
5 193/196
I'll leave the foldr one as an exercise.
About folds and standards
The folds in #!racket are racket specific. In Scheme, more precisely #!r6rs you have fold-left and fold-right and unlike #!racket the argument order from a left to a right changes making it more similar to the *new Haskell version.
SRFI-1 list library uses the names fold and foldr and expect the same argument order for both, just like #!racket. SRFI-1 also supports different length lists and stops at the shortest one so it is the one with most features. SRFI-1 can be included in both #!racket with (require srfi/1)and with #!r6rs. (import (rnrs :1))
Haskell's foldr and foldl are not exactly equivalent to Racket's. Also, div is integer division, so you should use quotient in Racket. But even then,
(foldr quotient 7 (list 34 56 12 4 23)) => 8
(foldl quotient 7 (list 34 56 12 4 23)) => quotient: undefined for 0
You could read the documentation carefully on how foldl and foldr work, but I like to refer to the docs for the teaching languages:
(foldr f base (list x-1 ... x-n)) = (f x-1 ... (f x-n base))
(foldl f base (list x-1 ... x-n)) = (f x-n ... (f x-1 base))
So it becomes
(quotient 34 (quotient 56 (quotient 12 (quotient 4 (quotient 23 7)))))
(quotient 23 (quotient 4 (quotient 12 (quotient 56 (quotient 34 7)))))

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)

How to make two lists, one with even numbers and one with odd numbers, in scheme?

I have a problem.
For example:
We have one unsorted list:
(1 4 5 3 6 7)
Can you help me make 2 lists?
One odd numbered, increasing list:
(1 3 5 7)
and the other even numbered, decreasing list:
(6 4)
Don't use sort!
(define (split filter lst)
(let loop ((a '()) (b '()) (lst lst))
(if (null? lst)
(values a b)
(let ((cur (car lst)))
(if (filter cur)
(loop (cons cur a) b (cdr lst))
(loop a (cons cur b) (cdr lst)))))))
(split odd? '(1 2 3 4 5 6 7 8 9 10))
; ==> (9 7 5 3 1), (10 8 6 4 2)
Now, to make one that separates odds from evens and in a specific order would be simple.

Josephus in Scheme

Where does this implementation of the Josephus problem fall short? For those who are unfamiliar with the Josephus Problem, the goal is to delete every 3rd entry from a circularly linked list until only one remains. In this example I am deleting every "mth" value.
(define (joseph lst)
(let ((m (+ 1 (random (length lst)))))
(define (joseph-h i xlst mlst)
(cond ((<= (length xlst) 1) xlst)
((null? (cdr mlst))
(joseph-h i xlst xlst))
((= i m)
(joseph-h 1 (delete (car mlst) xlst) (cdr mlst)))
(else
(joseph-h (+ i 1) xlst (cdr mlst)))))
(joseph-h 0 lst lst)))
(joseph (list 1 2 3 4 5 6 7))
(define (delete v lst)
(cond ((= v (car lst))
(cdr lst))
(else
(cons (car lst) (delete v (cdr lst))))))
I always end up with the last number of the list as the answer. I know that this is not right.
You're taking the algorithm too literally, by creating a list and deleting elements ("killing" people) from it. A simpler solution would be to use arithmetic operations to model the problem, here's a possible implementation, adapted from my own previous answer:
(define (joseph n k)
(let loop ([i 1]
[acc 0])
(if (> i n)
(add1 acc)
(loop (add1 i)
(modulo (+ acc k) i)))))
For example, to see which position survives in the list '(1 2 3 4 5 6 7) after killing every third person, do this:
(joseph 7 3)
=> 4
Wikipedia provides an interesting discussion regarding the possible solutions for this problem, my solution adapts the simple python function shown, after converting it to tail recursion.
I give three solutions at my blog. The most literal version deletes from a list of n items in steps of m, representing the list as a cyclic list:
(define (cycle xs)
(set-cdr! (last-pair xs) xs) xs)
(define (josephus3 n m)
(let loop ((k (- m 1)) (alive (cycle (range 0 n))) (dead '()))
(cond ((= (car alive) (cadr alive))
(reverse (cons (car alive) dead)))
((= k 1)
(let ((dead (cons (cadr alive) dead)))
(set-cdr! alive (cddr alive))
(loop (- m 1) (cdr alive) dead)))
This does the deletions by actually removing the killed elements from the alive list and placing them on the dead list. The range function is from my Standard Prelude; it returns the integers from 0 to n-1:
(define (range first past . step)
(let* ((xs '()) (f first) (p past)
(s (cond ((pair? step) (car step))
((< f p) 1) (else -1)))
(le? (if (< 0 s) <= >=)))
(do ((x f (+ x s))) ((le? p x) (reverse xs))
(set! xs (cons x xs)))))
The original Josephus problem killed 41 men in steps of 3, leaving the 31st man as the survivor, counting from 1:
(josephus3 41 3)
(2 5 8 11 14 17 20 23 26 29 32 35 38 0 4 9 13 18 22 27 31 36
40 6 12 19 25 33 39 7 16 28 37 10 24 1 21 3 34 15 30)
You might also enjoy the other two versions at my blog.

Resources