Reputation: 107
The problem is when lists have a different length, any idea of how to do it?
I have to use functions like map
or something like that.
This is the code I wrote so far, it works with lists of the same length but it also needs to work with lists of different lengths:
(define (interleave list1 list2)
(flatten
[map (lambda (x y) (cons x (cons y null)))
list1 list2]))
When lists have different length this is the error that I get:
map: all lists must have same size;
arguments were: #<procedure> '(1 2 3 4 5) '(a b c)
I'm trying to get (1 a 2 b 3 c 4 5)
as the result here. Thank you.
Upvotes: 3
Views: 3289
Reputation: 71119
"There ain't nothin' you can't not do with fold-right
and some of them con-tin-uations thingies", said a cowboy to another, spittin' into the campfire and puffin' on his cigar in the evening, sippin' his black coffee from his rugged banged up tin mug. "Yessir, nothin' in the whole darn world."
(define (interleave xs ys)
;; interleave xs ys = foldr g n xs ys
;; where
;; g x r (y:ys) = x : y : r ys
;; g x r [] = x : r []
;; n ys = ys
((foldr
(lambda (x r)
(lambda (ys)
(cond ((null? ys) (cons x (r '())))
(else (apply (lambda (y . ys)
(cons x (cons y (r ys))))
ys)))))
(lambda (ys) ys)
xs)
ys))
Illustration:
interleave [a,b,c] [1,2,3,4,5]
(foldr g n [a,b,c]) [1,2,3,4,5]
(g a (foldr g n [b,c])) [1,2,3,4,5]
(g a (g b (g c n))) [1,2,3,4,5]
[a, 1, ...(g b (g c n)) [2,3,4,5]]
[a, 1, b, 2, ...(g c n) [3,4,5]]
[a, 1, b, 2, c, 3, ...n [4,5]]
[a, 1, b, 2, c, 3, ...[4,5]]
[a, 1, b, 2, c, 3, 4,5 ]
interleave [a,b,c,d] [1,2]
(foldr g n [a,b,c,d]) [1,2]
(g a (foldr g n [b,c,d])) [1,2]
(g a (g b (g c (g d n)))) [1,2]
[a, 1, ...(g b (g c (g d n))) [2]]
[a, 1, b, 2, ...(g c (g d n)) []]
[a, 1, b, 2, c, ...(g d n) []]
[a, 1, b, 2, c, d, ...n []]
[a, 1, b, 2, c, d, ...[]]
[a, 1, b, 2, c, d ]
Upvotes: 1
Reputation:
I'm assuming your desired behavior is that the lists are interleaved for as long as this is possible, and then whatever is left over from the nonempty list is appended to the end. In that case one possible implementation is
(define (interleave a b)
(if (null? a)
b
(cons (car a)
(interleave b (cdr a)))))
I think this is probably the simplest possible way to write what you're looking for.
Upvotes: 2
Reputation: 2186
A solution using simple list manipulation functions might be:
(define (interleave list1 list2)
(cond ((empty? list1) list2)
((empty? list2) list1)
(else
(append
(list (car list1) (car list2))
(interleave (cdr list1) (cdr list2))))))
Testing...
> (interleave '(1 2 3 4 5) '(a b c))
(1 a 2 b 3 c 4 5)
> (interleave '(1 2 3 4 5) '())
(1 2 3 4 5)
> (interleave '() '(a b c))
(a b c)
>
I think it is fairly self-documenting.
Upvotes: 1
Reputation: 31145
#lang racket
(define (weave xs ys)
(match (list xs ys)
[(list (cons x xs) (cons y ys)) (cons x (cons y (weave xs ys)))]
[(list '() ys) ys]
[(list xs '()) xs]))
Upvotes: 3
Reputation: 48775
Neither map
nor fold-right
would work because they either signal an error when one list is smaller than the other or they tend to stop at the shortest list. eg. SRFI-1's map (interleave '(1 2 3 4) (circular-list 9 8)) ; ==> (1 9 2 8 3 9 4 8)
. For a different behavior you need to roll your own.
Upvotes: 1