Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

re: Interleaving strings

128 views
Skip to first unread message

WJ

unread,
Mar 24, 2012, 10:38:03 AM3/24/12
to
Pascal J. Bourguignon wrote:

> Eric Wolf <e...@boese-wolf.eu> writes:
> > Hi there!
>
> > I want to have a function, which interleaves strings. So if the input is
> > "aaa" "bbb" the result should be "ababab". If the input is "aaaa" "bbb"
> > "cc" the result shall be "abcabcaba". So you just put a character from
> > the first string into the result string then you put a character from
> > the second string into the result strings and so, until all input
> > strings are exhausted.
>
> > This is what I came up with, but I'm wondering, if there aren't better
> > ways in *Common Lisp*, which I'm not able to see. (Comings from C++ and
> > the likes):
>
> > (defun interleave-strings (&rest args)
> > (if args
> > (let* ((result-length (apply #'+ (mapcar #'length args)))
> > (erg (make-array `(,result-length)
> > :element-type 'character
> > :fill-pointer 0)))
> > ;;prepare the input, so we can count the used characters in a string
> > ;;and know, when it is exhausted.
> > (setf args (mapcar #'(lambda (arg)
> > (list 0 (length arg) arg))
> > args))
> > ;;keep the last cons cell in mind
> > (let ((last (last args)))
> > ;;create a circular list, so we can wrap around
> > (setf (cdr last) args)
> > ;;loop over the circular list, keeping the actual position and the
> > ;;position before
> > (do* ((oldpos last pos)
> > (pos args (cdr pos))
> > (elem (car args) (car pos)))
> > ((null elem) erg)
> > (vector-push (char (third elem) (first elem)) erg)
> > (incf (first elem))
> > (if (not (< (first elem) (second elem)))
> > (if (eql pos oldpos)
> > ;;if its the last remaining item, clear the circular list
> > (setf oldpos nil
> > pos nil)
> > ;;if there are more then one item, delete one entry
> > (setf (cdr oldpos) (cdr pos)
> > pos oldpos))))))
> > ""))
>
> > Please comment and suggest better ways.
>
> > Yours sincerely,
>
> > Eric
>
> (defun interleave-strings (&rest strings)
> (with-output-to-string (*standard-output*)
> (loop
> :with indexes = (make-array (length strings) :initial-element 0)
> :with len = (reduce (function max) strings :key (function length))
> :for done = t
> :do (map-into indexes (lambda (string index)
> (when (< index (length string))
> (princ (aref string index))
> (incf index)
> (setf done nil))
> index)
> strings indexes)
> :until done)))
>
> (defun test/interleave-strings ()
> (assert (string= (interleave-strings "aaa" "bbb") "ababab"))
> (assert (string= (interleave-strings "aaaa" "bbb" "cc") "abcabcaba"))
> :success)


Clojure:

(defn interleave-strings [& strings]
(let [maxlen (apply max (map count strings))]
(->> strings
(map #(into (vec %) (repeat (- maxlen (count %)) nil)))
(apply interleave)
(remove nil?)
(apply str))))

(interleave-strings "aaa" "bbb")
==> "ababab"
(interleave-strings "aaaa" "bbb" "cc")
==> "abcabcaba"

namekuseijin

unread,
Mar 25, 2012, 3:12:21 PM3/25/12
to
I've got this really trivial list-processing function here (in Scheme):

(define (weave l1 l2)
(cond
((null? l1) l2)
((null? l2) l1)
(else `(,(car l1) ,(car l2) ,@(weave (cdr l1) (cdr l2))))))

so

(weave '(a a a) '(b b b))
=> (a b a b a b)

it's now trivial to handle strings:

(define (weave-strings x y)
(list->string (weave (string->list x) (string->list y))))

WJ

unread,
Apr 15, 2013, 10:04:23 PM4/15/13
to
Why this is marked as abuse? It has been marked as abuse.
Report not abuse
Instead of CL, tCL.

package require Tclx
namespace path {tcl::mathop tcl::mathfunc}

proc interleave_chars args {
set last [max {*}[lmap s $args {string length $s}]]
set result ""
loop i 0 $last {
foreach str $args {append result [string index $str $i]}}
return $result}

% interleave_chars "aaa" "bbb"
ababab
% interleave_chars "aaaa" "bbb" "cc"
abcabcaba

WJ

unread,
Apr 19, 2013, 11:55:31 PM4/19/13
to
Lua:

require "std"

function interleave_chars (...)
local last =
math.max(table.unpack(list.map(string.len, table.pack(...))))
local result = ""
for i = 1,last do
for _,str in ipairs( table.pack(...)) do
result = result .. string.sub( str, i, i)
end
end
return result
end

> = interleave_chars( "aaaa", "bbb", "cc" )
abcabcaba

WJ

unread,
Dec 17, 2013, 4:58:58 PM12/17/13
to
Clojure:

(defn interleave-chars [& strings]
(loop [strings strings, result ""]
(if (every? empty? strings)
result
(recur (map rest strings)
(str result (clojure.string/join (map first strings)))))))

user=> (interleave-chars "aaa" "bbb")
"ababab"
user=> (interleave-chars "aaaa" "bbb" "cc")
"abcabcaba"
user=> (interleave-chars "a" "bb" "cccc")
"abcbccc"

Paul Rubin

unread,
Dec 17, 2013, 6:16:54 PM12/17/13
to
"WJ" <w_a_...@yahoo.com> writes:
> (defn interleave-chars [& strings]
> (loop [strings strings, result ""] ...

Oh cool, I didn't realize Clojure had LOOP. Almost like Common Lisp!

interleave [] = []
interleave ss = map head nn ++ interleave (map (drop 1) nn)
where
nn = filter (not.null) ss

Marco Antoniotti

unread,
Dec 18, 2013, 6:53:30 AM12/18/13
to
Hey! That's a LOOP in Haskell! :)

MA

WJ

unread,
Jun 16, 2014, 12:12:58 PM6/16/14
to
elisp:

(defun interleave-chars (&rest strings)
(let (result)
(dotimes (i (apply 'max (mapcar 'length strings)))
(dolist (str strings)
(when (< i (length str))
(push (elt str i) result))))
(concat (reverse result))))

: (interleave-chars "aaa" "bbb")
"ababab"
: (interleave-chars "aaaa" "bbb" "cc")
"abcabcaba"
: (interleave-chars "aaaa" "bbb" "cc" "ddddd")
"abcdabcdabdadd"

WJ

unread,
Mar 25, 2015, 1:29:33 AM3/25/15
to
Gauche Scheme:

(use srfi-13) ; string-null? string-drop
(use gauche.collection) ; map-to

(define (interleave-chars . strings)
(let go ((strings strings))
(let1 strings (remove string-null? strings)
(if (null? strings)
""
(string-append
(map-to <string> (cut ref <> 0) strings)
(go (map (cut string-drop <> 1) strings)))))))

(interleave-chars "aaa" "bbb")
===>
"ababab"

(interleave-chars "aaaa" "bbb" "cc")
===>
"abcabcaba"

(interleave-chars "a" "bb" "cccc")
===>
"abcbccc"

WJ

unread,
Apr 4, 2016, 7:34:17 AM4/4/16
to
Why this is marked as abuse? It has been marked as abuse.
Report not abuse
OCaml:

open List ;;

let interleave_strings strings =
let lengths = (map String.length strings) in
let buffer = Buffer.create (fold_left (+) 0 lengths) in
for i = 0 to (fold_left max 0 lengths) - 1 do
iter
(fun s -> try Buffer.add_substring buffer s i 1
with Invalid_argument _ -> ())
strings
done ;
Buffer.contents buffer ;;

interleave_strings ["aaaa"; "bbb"; "c"];;
===>
"abcababa"

interleave_strings ["aa"; "bbb"; "cccc"];;
===>
"abcabcbcc"

--
The goal is to meet the EU challenge of interracial marriage. It's not a
choice. It's an obligation. If voluntarism does not work for the republic,
then the state will move in with more coercive measures.
--- the Jew Nicolas Sarkozy (www.youtube.com/watch?v=K0hD7IffTJs)
0 new messages