Alternating Lists
February 1, 2019
This is simple enough:
(define (alternate . xss) (let loop ((xss xss) (zs (list))) (cond ((null? xss) (reverse zs)) ((null? (car xss)) (loop (cdr xss) zs)) (else (loop (append (cdr xss) (list (cdar xss))) (cons (caar xss) zs))))))
The only trick is the expression (list (cdar xss))
, where the list
is required to keep the data structure as a list of lists. Here’s the example problem, with added output to show what is happening inside the loop:
> (alternate '(1 2 3 4 5) '(a b c) '(w x y z))
((1 2 3 4 5) (a b c) (w x y z)) ()
((a b c) (w x y z) (2 3 4 5)) (1)
((w x y z) (2 3 4 5) (b c)) (a 1)
((2 3 4 5) (b c) (x y z)) (w a 1)
((b c) (x y z) (3 4 5)) (2 w a 1)
((x y z) (3 4 5) (c)) (b 2 w a 1)
((3 4 5) (c) (y z)) (x b 2 w a 1)
((c) (y z) (4 5)) (3 x b 2 w a 1)
((y z) (4 5) ()) (c 3 x b 2 w a 1)
((4 5) () (z)) (y c 3 x b 2 w a 1)
(() (z) (5)) (4 y c 3 x b 2 w a 1)
((z) (5)) (4 y c 3 x b 2 w a 1)
((5) ()) (z 4 y c 3 x b 2 w a 1)
(() ()) (5 z 4 y c 3 x b 2 w a 1)
(()) (5 z 4 y c 3 x b 2 w a 1)
() (5 z 4 y c 3 x b 2 w a 1)
(1 a w 2 b x 3 c y 4 z 5)
You can run the program at https://ideone.com/qt9FQ7.
In Ruby. Assumes elements are in the lists are not nil.
Mumps version
1 a w 2 b x 3 c y 4 z 5
— Here’s some Haskell, I’ll leave it to enthusiasts to convert to pointfree style.
In Python.
I think my solution is a bit simpler:
(define (alternate x . y)
(cond
((null? y) x)
((null? x)
(apply alternate y))
(else
(cons
(car x)
(apply
alternate
(append y (list (cdr x))))))))
Here’s another Haskell solution. (In pointfree style! :-)
@Globules: very nice – it would be good to have a pointfree definition of transpose as well!
Here’s another Haskell version, this one is a simplification of a modification of the Haskell library definition of transpose. I’ve not seen that list comprehension with partial matches idiom before:
And here’s a pointfree Haskell solution that doesn’t seem too incomprehensible:
Here’s an simple-minded scheme solution with filter and map:
(define (not-null? x) (not (null? x)))
(define (splice . lists)
(let ((flists (filter not-null? lists)))
(if (not-null? flists)
(append (map car flists)
(apply splice (map cdr flists)))
'())))
Here’s a solution in C that uses linked lists.
Example:
Here’s a more raw, packageless python implementation I thought of:
def alternator(lists):
max_len = 0
if name == “main“:
lists = [[1,2,3,4,5],[‘a’,’b’,’c’],[‘w’,’x’,’y’,’z’]]
alternator(lists)
Here’s a solution in Common Lisp.
Example.
Here’s a solution in C that uses arrays.
Example:
Here’s a solution in Python.
Output: