Discussion:
Interleaving strings
(too old to reply)
Robert L.
2020-01-04 10:22:21 UTC
Permalink
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
(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)
Gauche, Chicken, or Racket

(use srfi-1) ; make-list for Chicken

(define (list-of-string str len)
(append
(map string (string->list str))
(make-list (- len (string-length str)) "")))

(define (interleave-strings . strings)
(let* ((len (apply max (map string-length strings)))
(lists (map (lambda (s) (list-of-string s len)) strings)))
(apply string-append (apply map string-append lists))))

(interleave-strings "aa" "bb" "cc")
===>
"abcabc"

(interleave-strings "a" "bb" "cc")
===>
"abcbc"

(interleave-strings "aa" "bb" "c")
===>
"abcab"

(interleave-strings "aa" "bbbbb" "c")
===>
"abcabbbb"

(interleave-strings "aa" "bbbb" "cc")
===>
"abcabcbb"
Robert L.
2020-01-04 18:27:22 UTC
Permalink
(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))
Note his error. He assigns a value to len and then
never uses it.
: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)))
A good example of the wrong way to program.

There are two ways of constructing a software design: One way is
to make it so simple that there are obviously no deficiencies,
and the other way is to make it so complicated that there are no
obvious deficiencies.
--- Charles Antony Richard Hoare
Robert L.
2020-01-05 00:07:19 UTC
Permalink
Post by Robert L.
(define (list-of-string str len)
(append
(map string (string->list str))
(make-list (- len (string-length str)) "")))
(define (interleave-strings . strings)
(let* ((len (apply max (map string-length strings)))
(lists (map (lambda (s) (list-of-string s len)) strings)))
(apply string-append (apply map string-append lists))))
Shorter.

Gauche, Chicken, or Racket

(use srfi-42) ; string-ec for Gauche or Chicken
or
(require srfi/42) ; string-ec for Racket

(define (interleave-strings . strings)
(let ((len (apply max (map string-length strings))))
(string-ec (:range i len)
(:list s strings)
(if (< i (string-length s)))
(string-ref s i))))
--
Among the passengers who were taken prisoner was the young journalist Winston
Churchill, whose life Ricchiardi spared by pretending not to see him dumping
his pistol and dum-dum ammunition which had been declared unlawful on pain of
death. Archive.org/details/nolies
Loading...