Interleave strings

Inspiration.* I cannot believe we have not had this challenge before:

Given one or more printable ASCII strings, interleave them by taking one character from each string, cyclically until out of characters. If a string runs out of characters before the others, just skip that one from then on.

Examples

SIMPLE gives SIMPLE

POLLS and EPEES gives PEOPLELESS

LYES and APRONS gives LAYPERSONS

ABCDE and a c and 123 567 gives Aa1B 2Cc3D E567

"\n$?* and (empty string) and ,(.)" (trailing space) gives ",\(n.$)?"* (trailing space)

* There are shorter APL solutions.

• Since this is basically just a transpose operation, we've had a few challenges that are very similar, but possibly none that are exactly the same. Dec 8 '16 at 12:10
• I had this question on my CS HW, does that mean I can close this as a homework question? ;P Dec 8 '16 at 14:40
• @EriktheOutgolfer Cool! I learned something today.
Apr 16 '17 at 6:42

Jelly, 1 byte

Z

Try it online!

The “transpose” built-in will do exactly this to a list of strings.

• I'm curious, what would the code have looked like if you had to pad short strings with spaces?
Dec 8 '16 at 13:33
• That would be z⁶. z is “transpose left, padding with right”; is a space.
– Lynn
Dec 8 '16 at 13:47
• @Adám Jelly works very well on lists; where do built-ins end and language constructs / design begin? Dec 8 '16 at 15:44
• @Lynn In Jelly? Anything on the Atoms and Quicks lists are buildt-ins.
Dec 8 '16 at 16:08
• @Adám ;" (element-wise concatenation) would solve the task without a built-in. Dec 8 '16 at 17:04

Python 2, 1018986 69 bytes

I'm hoping I can get this into a lambda somehow, shortening it down by making it recursive. It isn't ideal because you would hope transposing is shorter, unfortunately it isn't (from what I have managed to come up with so far).

f=lambda s:' '*any(s)and''.join(x[:1]for x in s)+f([x[1:]for x in s])

Old solutions:

w=input();o=''
while any(w):
for i in range(len(w)):o+=w[i][:1];w[i]=w[i][1:]
print o

lambda s:''.join(''.join([c,''][c<' ']for c in x)for x in map(None,*[list(y)for y in s]))

w=input();o=''
while any(x>=' 'for x in w):
for i in range(len(w)):o+=w[i][:1];w[i]=w[i][1:]
print o

thanks to mathmandan for making me feel dumb ;) saved me a bunch of bytes! (on an old solution)

• Couldn't you just do while any(w):? Empty strings are falsey in Python. Dec 8 '16 at 13:30
• @mathmandan You're absolutely right, don't know what I was thinking..
Dec 8 '16 at 13:33
• No problem :) Your new solution looks great, except I think you need to prepend f=. Dec 8 '16 at 13:54
• You can take the [] off of the recursive call, leaving f(x[1:] for x in s), that makes it a generator comprehension, which acts the same as a list in this context. Aug 1 '17 at 17:37

Perl 6, 34 32 bytes

{[~] flat roundrobin |$_».comb} {roundrobin(|$_».comb).flat.join}

A lambda that takes an array of strings as argument, and returns a string.

• I would have used @_ instead of $_ Dec 8 '16 at 19:13 CJam, 4 bytes qN/z Try it online! We can also write an unnamed function for 4 bytes, which expects a list of strings on top of the stack: {zs} Try it online! • That's one byte a minute! – Adám Dec 8 '16 at 12:12 Pyth - 3 bytes Very simple, will add expansion later, on mobile. s.T Test Suite s Join all the strings together .T Transpose, without chopping off overhang (Q implicit) • @Daniel I'm in school too :P Dec 8 '16 at 14:31 • Any plans on adding the explanation? Apr 14 '17 at 14:14 • @JanDvorak sure doing it now. Apr 16 '17 at 0:17 JavaScript (ES6), 52 46 bytes f=([[c,...s],...a])=>s+a?c+f(s+s?[...a,s]:a):c Takes input as an array of strings and outputs as a single string. Test snippet f=([[c,...s],...a])=>s+a?c+f(s+s?[...a,s]:a):c g=a=>console.log("Input:",JSON.stringify(a),"Output:",JSON.stringify(f(a))) g(["SIMPLE"]) g(["POLLS","EPEES"]) g(["LYES","APRONS"]) g(["ABCDE","a c","123 567"]) g(["\"\\n$?*",",(.)\" "]) // Backslash and quote are escaped, but in/output are correct

• f=([[c,...s],...a])=>c?c+f([...a,s]):a+a&&f(a)
– Neil
Dec 8 '16 at 14:06
• @Neil That's a great approach. I managed to golf 6 bytes off my own :-) Dec 8 '16 at 15:35

import Data.List
concat.transpose

Try it on Ideone. Usage:

Prelude Data.List> concat.transpose$["ABCDE","a c","123 567"] "Aa1B 2Cc3D E567" Without using a build-in: (38 34 bytes) f[]=[] f x=[h|h:_<-x]++f[t|_:t<-x] Try it on Ideone. 4 bytes off thanks to Zgarb! Usage: Prelude> f["ABCDE","a c","123 567"] "Aa1B 2Cc3D E567" • You can remove all parens in the alternative version. Still won't beat the import though. Dec 8 '16 at 16:46 • Do you actually need the base case? – xnor Dec 8 '16 at 17:16 • Never mind, of course the base case is needed. – xnor Dec 8 '16 at 17:24 • @xnor You also can't move the base case to the end and replace it with f a=a to save a byte because both [] have a different type ... so close. Dec 8 '16 at 19:46 C, 114 84 bytes -20 bytes for not calculating the length. i,b;f(char**s){b=1;while(b){i=-1;b=0;while(s[++i]>0)if(*s[i])putchar(*s[i]++),++b;}} Accepts array of char pointers and requires last item to be a null-pointer (see usage). Ungolfed and usage: i,b;f(char**s){ b=1; while(b){ i=-1; b=0; while(s[++i]>0) if(*s[i]) putchar(*s[i]++),++b; } } int main(){ char*a[]={ // "POLLS","EPEES" // "LYES","APRONS" "ABCDE","a c","123 567" ,0}; f(a); puts(""); } • Does the usage of printf/sprintf not allowed ? :D you would win quite some bytes. Dec 8 '16 at 14:18 • @Walfrat Without printing directly I'd need to allocate a string, so how could this save anything. Dec 8 '16 at 14:22 • it was before your edit where you added the ++b and remove length compute, so yes can't work anymore. Dec 8 '16 at 14:26 • @Walfrat Yes, but i had a malloc and return before and this was longer than just printing Dec 10 '16 at 18:50 PHP, 68 67 bytes for(;$f=!$k=$f;$i++)for(;y|$v=$argv[++$k];$f&=""==$c)echo$c=$v[$i]; Loops over command line arguments. Run with -r. After the inner loop,$f is 1 when all strings are finished, 0 else (bitwise & casts ""==$c to int). Next iteration of the outer loop: copy$f to $k (saves one byte from$k=0) and toggle $f: When all strings are done,$f is now false and the loop gets broken.

• Doesn't work with empty input strings. Take a look at the last testcase Dec 9 '16 at 11:01
• @aross: fixed. thanks. Dec 9 '16 at 14:26

Retina, 13 bytes

Byte count assumes ISO 8859-1 encoding.

O$#.$.%
¶

Try it online!

Explanation

O$#.$.%

This is based on the standard transposition technique in Retina. We sort (O) all non-linefeed characters (.), by ($#) the number of characters in front of them on the same line ($.%), i.e. their horizontal position.

The second stage then simply removes linefeeds from the input.

Java, 19+155=174 160

Ungolfed:

String f(java.util.Queue<String> q) {
String s, r = "";
while (!q.isEmpty()) {
s = q.poll();
r += s.isEmpty() ? "" : s.charAt(0);
if (s.length() > 1) {
}
}
return r;
}

Output:

SIMPLE

PEOPLELESS

LAYPERSONS

Aa1B 2Cc3D E567

",(n.$)?"* ​ First modification: merged string declaration to save some bytes. Removed import, it was used by the main() method (not shown here) that also needed LinkedList. It is fewer bytes to referece Queue directly. • initialize string s with string r can save few more Dec 9 '16 at 11:10 • I know it's been almost a year ago, but you can golf a few bytes: String f(java.util.Queue<String>q){String s,r="";for(;!q.isEmpty();r+=s.isEmpty()?"":s.charAt(0))if((s=q.poll()).length()>1)q.add(s.substring(1));return r;} Sep 6 '17 at 8:55 PHP, 77 bytes Golfed function($a){for($d=1;$d!=$s;$i++){$d=$s;foreach($a as$v)$s.=$v[$i];}echo$s;}

Anonymous function that takes an array of strings.

I'm sure this could be golfed more, but it's early. On each iteration, we grab the i-th letter from each given string and append it to our final string, one at a time. PHP just throws warnings if we access bits of strings that don't exist, so that's fine. We only stop when no changes have been made after looping through all the strings once.

Explanation

for(                       # Iterate over string index.
;
$s ^= 1; # Continue until$s (stop iterating) is 1.
# Flip $s so each iteration starts with$s
# being 1.

Try it online!

R, 73 bytes

for(i in 1:max(nchar(s<-scan(,""))))for(j in seq(s))cat(substr(s[j],i,i))

Try it online!

Explanation: very simple (but verbose), just loop through printing ith character of the jth string. Fortunately, substr returns an empty string if given an out-of-range input.

Python, 112 bytes

i=len(x)if len(x)>len(y) else len(y) h=0 a="" while h<i: if h<len(x) a+=x[h] if h<len(y): a += y[h] h+=1 print a
• Your formatting is really messed up.. where do you even get x and y from?
Dec 8 '16 at 13:35

"\",\\(n.$)? *" The weave function is lazy, so it returns a list, which is why we have to force the result to a string. Being lazy, it can weave infinite sequences. For instance, we can weave the even and odd natural numbers, which are themselves infinite lazy lists: 5> (take 20 (weave (range 2 : 2) (range 1 : 2))) (2 1 4 3 6 5 8 7 10 9 12 11 14 13 16 15 18 17 20 19) K (oK), 35 29 bytes Solution: {c$r@&~^r:,/+(i$x)[;!#,/x]} Try it online! Example: > {c$r@&~^r:,/+(i$x)[;!#,/x]}("ABCDE";"a c";"123 567") "Aa1B 2Cc3D E567" > {c$r@&~^r:,/+(i$x)[;!#,/x]}("\n$?*";"";",(.)\" ")
"\n,$(?.*)\" " > {c$r@&~^r:,/+(`i$x)[;!#,/x]}("POLLS";"EPEES") "PEOPLELESS" Explanation: Use 2nd-level indexing to pull out indices from 0 to max (length of flattened list) across all input lists. Any indexing beyond the bound of the sub-list will return a null. Flip (rotates 90), flatten, and then pull out the non-null results. Notes: • I cast to integer (i$) so that we get useful nulls, as space () is considered null for a char list which means you cant tell nulls from valid spaces.
• Also I couldnt get the TIO to work with input (worked fine in the oK repl) so the TIO link includes the "ABCDE"... example.

Jq 1.5, 49 bytes

map(explode)|transpose|map(map(values)[])|implode

Explanation

# example input:          ["LYES","APRONS"]
map(explode)        # make list of ordinals   [[76,89,69,83],[65,80,82,79,78,83]]
| transpose           # zip lists               [[76,65],[89,80],[69,82],[83,79],[null,78],[null,83]]
| map(map(values)[])  # rm nulls and flatten    [76,65,89,80,69,82,83,79,78,83]
| implode             # convert back to string  "LAYPERSONS"

Sample Run

$paste input <(jq -Mrc 'map(explode)|transpose|map(map(values)[])|implode' input) ["SIMPLE"] SIMPLE ["POLLS","EPEES"] PEOPLELESS ["LYES","APRONS"] LAYPERSONS ["ABCDE", "a c", "123 567"] Aa1B 2Cc3D E567 ["\"\\n$?*", "", ",(.)\" "] ",\(n.$)?"*$ echo -n 'map(explode)|transpose|map(map(values)[])|implode' | wc -c
49

Try it online