# Overlapping String-Blocks

## Challenge:

Given a list of multi-line strings, overlap them (in the top-left) and output the result.

Example:

Input: ["aaaa\naaaa\naaaa\naaaa","bb\nbb\nbb","c"]
Output:

cbaa
bbaa
bbaa
aaaa


## Challenge rules:

• Input-format is flexible. You are allowed to get the input as a 2D list of lines (i.e. [["aaaa","aaaa","aaaa","aaaa"],["bb","bb","bb"],["c"]]) or 3D list of characters (i.e. [[["a","a","a","a"],["a","a","a","a"],["a","a","a","a"],["a","a","a","a"]],[["b","b"],["b","b"],["b","b"]],[["c"]]]). You are allowed to take all the inputs one by one through STDIN. Etc.
• Output format is strict. You can choose to print or return the multi-line string. (If your language doesn't have any strings, outputting as a 2D list of characters is allowed as alternative. But only if your language doesn't have strings at all.)
• The order of the input-list is of course important (but you are allowed to take the input in reverse if you choose to).
• Inputs will only contain printable ASCII in the unicode range $$$33,126]\$$ (!"#%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[$^_abcdefghijklmnopqrstuvwxyz{|}~).
• Inputs will only be rectangles (so no weird shapes). The output aren't necessary rectangles, though.
• Trailing spaces and a single trailing newline is allowed. Leading spaces and/or newlines not.

## General rules:

• This is , so shortest answer in bytes wins.
Don't let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for 'any' programming language.
• Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
• Default Loopholes are forbidden.

## Test cases:

Input: ["aaaa\naaaa\naaaa\naaaa","bb\nbb\nbb","c"]
Output:

cbaa
bbaa
bbaa
aaaa


Input: ["12345\n54321","00\n00\n00\n00","001\n011\n012"]
Output:

00145
01121
012
00


Input: ["sm\noo\nmr\nee\nt!\nh_\ni_\nn_\ng_","!@#$%^\n&*()_+\nqwerty\nuiopas","this\nis_a\ntest"] Output: this%^ is_a_+ testty uiopas t! h_ i_ n_ g_  • Are trailing newlines allowed? Or more specifically, is an arbitrary amount of trailing newlines allowed? – JAD Jun 5 '19 at 14:29 • @JAD Yeah sure, why not. As long as the rest is output without any leading spaces/newlines. Trailing newlines/spaces aren't really important, so can optionally be added. – Kevin Cruijssen Jun 5 '19 at 17:29 ## 22 Answers # Jelly, 3 bytes a/Y  Try it online! Hadn't used Jelly in a while but I thought the challenge in the comments was beatable. Very directly uses logical and (a) to perform the stacking operation between each element of the input (/). Y is used to print in the required format. • Ah nice! I'm pretty bad with Jelly tbh. My prepared solution was ḷ""/Y with a reversed input-list. Didn't even knew about a.. – Kevin Cruijssen Jun 4 '19 at 17:10 # JavaScript (Node.js), 24 bytes Saved 2 bytes thanks to @Grimy Assumes that the returned string is printed on a terminal that supports ANSI escape codes. Contains the unprintable character ESC, which is escaped (no pun intended) as \x1B below. a=>\x1B[2J\x1B[H+a.join\x1B[H  This doesn't work on TIO, but you can Try it online! to see the raw output instead. ### How? The CSI sequences used are: • ED (Erase in Display): ESC[2J where $$\2\$$ means "clear entire screen" • CUP (Cursor Position): ESC[H which means "moves the cursor to row $$\n\$$, column $$\m\$$" where both $$\n\$$ and $$\m\$$ are omitted and implicitly set to $$\1\$$ (top-left corner of the screen). ### Example output • Assuming an ECMA-48 compliant terminal, you can omit both ;. Also, I think this should be "JavaScript + terminal" or something similar that doesn't compete with pure JavaScript. – Grimmy Jun 4 '19 at 15:12 • @Grimy Thanks! (For anyone interested, here is the ECMA-48 specification -- but I didn't find where it's mentioned that the semicolon can be omitted -- if it's mentioned at all.) – Arnauld Jun 4 '19 at 15:27 • 5.4.2.h is somewhat confusingly worded, but the interesting bit is: if the last parameter sub-string(s) is empty, the separator preceding it may be omitted. Since there are only two sub-strings, the separator preceding the last substring is the only one, and it can be omitted. – Grimmy Jun 4 '19 at 15:36 • I don't know ANSI, but is the first \x1B[H+ necessary? Isn't it starting at the top-left by default, and you only need to reset it after each input (which is what join does)? Or does it initially start somewhere else by default, and you have to explicitly let it start at that cursor position for it to successfully reset to that position in the join? – Kevin Cruijssen Jun 4 '19 at 15:46 • @Arnauld Since you probably will always have something else on the terminal when executing this function, I guess the initial reset is required after all. As for ommitting print, I guess f=a=>print(\x1B[H+a.join\x1B[H) with f(input_here) would produce the same output as print(f(input_here))? So I don't see why you wouldn't be allowed to omit the print and simply return a string. – Kevin Cruijssen Jun 4 '19 at 16:29 # R, 120, 111110 107 bytes function(x,!=ncol,M=array('',Reduce(pmax,Map(dim,x)))){for(m in x)M[1:!t(m),1:!m]=m write(t(M),1,!M,,'')}  Try it online! A function accepting a list of matrix of characters (3D input is accepted). (as you can notice from the byte count, this is not very easy to do in R...) • -9 bytes thanks to @Giuseppe • -4 bytes thanks to @RobinRyder • I was really expecting a 200+ byte solution! I'll be giving this a nice bounty whenever this question becomes bounty eligibile – Giuseppe Jun 4 '19 at 20:19 • @Giuseppe: still much longer than other languages ... :( – digEmAll Jun 4 '19 at 20:21 • 111 bytes using array instead of matrix! – Giuseppe Jun 4 '19 at 20:35 • @Giuseppe: neat ! – digEmAll Jun 4 '19 at 20:41 • 107 with an alias for ncol (you can transpose to get nrow). – Robin Ryder Jun 4 '19 at 20:51 # Python 2, 88 bytes n,f=None,filter for l in map(n,*input()):print''.join(f(n,x)[-1]for x in map(n,*f(n,l)))  Try it online! ### Explanation (with example): Takes a 2D list as input. Input: [["12345","54321"],["00","00","00","00"],["001","011","012"]]  First the input list is zipped, to get the rows of each input rectangle (map(None,l) is the same a zip longest): map(n,*input()) gives: ('12345', '00', '001') ('54321', '00', '011') (None, '00', '012') (None, '00', None)  Each of these rows are then filtered to removed Nones, and zipped again: map(None,*filter(None,l)) filter(None,l) for each l gives: ('12345', '00', '001') ('54321', '00', '011') ('00', '012') ('00',) map*... gives: [('1', '0', '0'), ('2', '0', '0'), ('3', None, '1'), ('4', None, None), ('5', None, None)] [('5', '0', '0'), ('4', '0', '1'), ('3', None, '1'), ('2', None, None), ('1', None, None)] [('0', '0'), ('0', '1'), (None, '2')] ['0', '0']  Which is a list of characters for each position of the desired result. These lists are filtered again, and the last one is taken: filter(None,x) gives: [('1', '0', '0'), ('2', '0', '0'), ('3', '1'), ('4',), ('5',)] [('5', '0', '0'), ('4', '0', '1'), ('3', '1'), ('2',), ('1',)] [('0', '0'), ('0', '1'), ('2',)] ['0', '0'] and with [-1]: ['0', '0', '1', '4', '5'] ['0', '1', '1', '2', '1'] ['0', '1', '2'] ['0', '0']  Lastly the resulting lists are joined and printed: print''.join(..) 00145 01121 012 00  • RE "Returns a list of strings", the rules state "Output format is strict. You can choose to print or return the multi-line string. 2D or 3D lists as outputs aren't allowed.". The 88 byte full program seems fine though – Jonathan Allan Jun 4 '19 at 17:00 • @JonathanAllan, welp, I misread the strict output (or forgot? :p) – TFeld Jun 4 '19 at 18:30 # R, 107 97 bytes function(x)for(i in 1:max(lengths(x))){for(m in x)if(i<=length(m))cat(m[i],'\r',sep='');cat(' ')}  Doesn't appear to work on TIO, which might be related to the use of the \r carriage return character. It does work on my local installation of R. Takes input as a list containing a vector of rows: x <- list(c("aaaa","aaaa","aaaa","aaaa"),c("bb","bb","bb"),c("c"))  Loops over the rows of each rectangle, printing a carriage return after each, restarting the line. If we stretch the rules a little, we can do away with checking the length of the input and just loop infinitely, printing a huge amount of newlines: # R, 85 bytes function(x)for(i in 1:8e8){for(m in x)if(i<=length(m))cat(m[i],'\r',sep='');cat(' ')}  • 106 bytes Nice to see you doing a golf here and there! – Giuseppe Jun 5 '19 at 14:05 • Possibly 97 bytes; unclear if this actually works since I'm only testing in TIO – Giuseppe Jun 5 '19 at 14:08 • @Giuseppe Hi! Your suggestion works for me. If we are allowed to print trailing newlines, it's also possible to just use an arbitrarily big for loop instead, but I guess that's pushing the limits of the challenge. – JAD Jun 5 '19 at 14:32 • @JAD: great idea using \r, and welcome back! Just a note, I think this works only in interactive R sessions (when interactive() returns true) – digEmAll Jun 5 '19 at 19:06 • @digEmAll It works on my machine using rscript from commandline. I suspect it's a Windows/Linux thing, since Windows uses \r\n for newlines and Linux \n. – JAD Jun 6 '19 at 6:25 # APL (Dyalog Unicode), 22 bytesSBCS Anonymous tacit prefix function taking list of 2D character arrays as argument. Prints. (⊃{⍺@(⍳⍴⍺)⊢⍵}/)⌽,∘⊂1⌷↑  Try it online! This works by creating a canvas, then appending that to the list of blocks, and reducing (folding) with a function that places blocks in the corner. ↑ mix the 2D block to create an orthogonal 3D block, padding them with spaces as needed 1⌷ take the first layer ⊂ enclose that ∘ then ⌽, prepend the reversed list of blocks () apply the following tacit function: {}/ reduce using the following anonymous lambda: ⊢⍵ with the right argument as canvas… ⍺@() amend with the elements of the left argument, placed at the following indices: ⍴⍺ the shape of the left argument ⍳ the ɩndices of an array of that shape ⊃ disclose (because the reduction enclosed to reduce rank) ## Haskell, 66 bytes unlines.foldl((const?)?)[] (g?(a:b))(c:d)=g a c:(g?b)d;(_?a)b=a++b  Input is taken as a list of list of strings in reverse order, e.g. for the first test case: [["c"],["bb","bb","bb"],["aaaa","aaaa","aaaa","aaaa"]]. Try it online! # 05AB1E, 12 bytes Port of TFeld's python solution 2 bytes saved thanks to Grimy ζεðKζðδK€θJ,  Try it online! Explanation ζ # transpose input with space as filler ε # apply to each ðK # remove spaces ζ # transpose with space as filler ðδK # deep remove spaces €θ # get the tail of each J # join each , # print  Alternative 14 byte version õζεÅ»DŠg.$J}θ,


Try it online!

Explanation

õζ              # zip with empty string as filler
ε             # apply to each
Å»      }    # cumulative reduce by
D          # duplicate second input
Š         # move down twice on stack
g.$# remove len(other_copy) elements from the other input J # join with other copy θ, # print the last element  • Oh, need to remember that --no-lazy is the fix to still use a map/filter with print for the implicit y, to save a byte in comparison to vy..., :) I knew that worked in the legacy version, but in the new version it would also output the [...]. Didn't knew that was due to the lack of --no-lazy. ;) As for the answer itself, very nice! I knew a cumulative reduce was necessary, but couldn't really work it out when I tried it myself. You make it look so easy.. – Kevin Cruijssen Jun 4 '19 at 14:04 • I had it mentioned in the rules, but forgot to apply it to the test cases.., but spaces won't be in the input. So you can probably save some bytes there since the zip-filler is a space by default. (Not sure if it saves anything in your first answer, but in the port it might.) – Kevin Cruijssen Jun 4 '19 at 14:40 • õζεõK can be ζεðK, õζõδK can be ζðδK. – Grimmy Jun 4 '19 at 15:06 • @Grimy: Oh yeah, spaces can no longer be in the input. Thanks! – Emigna Jun 4 '19 at 15:53 # Canvas, 5 bytes Ｈ１１╋╋  Try it here! If overlapping /+\X, - + |+, etc. would be fine, 2 bytes would work. # Python 2, 77 bytes for t in map(None,*input()): r='' for s in t: if s:r=s+r[len(s):] print r  Try it online! # PowerShell 6, console only, 20 bytes based on Arnauld's answer. This work with console only and doesn't work on TIO. cls$args-join"e[H"


Try it online!

# PowerShell, 103 bytes

$args|%{$l=$_-split' ';$r=&{$r+($l|%{''})|%{($x=$l[$j++])+($_-replace"^.{0,$("$x"|% Le*)}")}|?{$_}}}$r


Try it online!

Unrolled:

$args|%{$l=$_-split"n"$r=&{                           # run this scriptblock in a new scope
$r+($l|%{''})|%{
$x=$l[$j++] # a new line or$null
$w="$x"|% Length
$y=$_-replace"^.{0,$w}" # remove first chars from the current line$x+$y # output the new line plus tail of the overlapped line }|?{$_}                     # filter out not empty lines only
}                               # close the scope and remove all variables created in the scope
}

->i,*r{i.map{|e|j=-1;e.map{|l|r[j+=1]||='';r[j][0,l.size]=l}};r*$/}  Try it online! # C (GCC, MinGW) 138 bytes Assumes that CR puts the cursor at the start of the current line. d,i,l;f(S,n,p,t)char**S,*p,*t;{for(d=i=0;i<n;d+=l)p=strchr(t=S[i],10),printf("\n%.*s\r"+!!i,l=p?p-t:strlen(t),t),S[i++]+=l+!!p;d&&f(S,n);}  Tested with: int main() { char *test1[] = {"aaaa\naaaa\naaaa\naaaa","bb\nbb\nbb","c"}; char *test2[] = {"12345\n54321","00\n00\n00\n00","001\n011\n012"}; char *test3[] = {"sm\noo\nmr\nee\nt!\nh_\ni_\nn_\ng_","!@#$%^\n&*()_+\nqwerty\nuiopas","this\nis_a\ntest"};

f(test1, 3);
f(test2, 3);
f(test3, 3);
}


# Octave, 71 67 bytes

function y=f(x)
for k=1:size(x)
y(1:(t=size(x{k})),1:t(2))=x{k};end


Function that takes a vertical cell array of char matrices, and returns a char matrix.

# Javascript (browser), 216208 204 bytes

My attempt at this. I'm not happy about the size, and there must certainly be more for improvement, but I'm not that experienced at golfing.

var n='\n',x=s=>s.split.reverse().join,i,j,f=a=>a.map(s=>s.split(n).map(y=>x(y))).reduce((a,b)=>{for(i=0;i<b.length;i++){j=a[i];if(!j)j=b[i];a[i]=b[i].padStart(j.length,j)}return a}).map(s=>x(s)).join(n)


Anyways, what it does is first split all the strings, then reverse all the strings, then whilst looping in a reduce operation padStart all the strings together. Then reverse all the strings again and then join them back with newlines.

Special thanks to Kevin Cruijssen for reminding me that the last part in a for loop happens at the end and a total byte savings of 8 bytes.

var n='\n',x=s=>s.split.reverse().join,i,j,f=a=>a.map(s=>s.split(n).map(y=>x(y))).reduce((a,b)=>{for(i=0;i<b.length;a[i]=b[i++].padStart(j.length,j))if(!(j=a[i]))j=b[i];return a}).map(s=>x(s)).join(n)

console.log(f(["aaaa\naaaa\naaaa\naaaa","bb\nbb\nbb","c"]));
console.log(f(["12345\n54321","00\n00\n00\n00","001\n011\n012"]));
console.log(f(["sm\noo\nmr\nee\nt!\nh_\ni_\nn_\ng_","!@#$%^\n&*()_+\nqwerty\nuiopas","this\nis_a\ntest"])); • Both ('') can be two  to save four bytes :) – Kevin Cruijssen Jun 5 '19 at 13:43 • Also, you can replace the for(i=0;i<b.length;i++){j=a[i];if(!j)j=b[i];a[i]=b[i].padStart(j.length,j)} with for(i=0;i<b.length;a[i]=b[i++].padStart(j.length,j))if(!(j=a[i]))j=b[i];. – Kevin Cruijssen Jun 5 '19 at 13:45 • The j is first assigned with (j=a[i]), then the if-statement is done with if(!...)j=b[i]; (where ... is the (j=a[i]), so the updated value of j), and then the ;a[i]=b[i++].padStart(j.length,j)) is done at the end of the for-loop iteration.. Not sure where the problem is, and it seems to work? – Kevin Cruijssen Jun 5 '19 at 13:51 • ooohhh.... * big eyes * that unlocked something – Tschallacka Jun 5 '19 at 13:52 • Btw, if you haven't seen them yet, tips for golfing in <all languages> and tips for golfing in JavaScript might both be interesting to read through. :) – Kevin Cruijssen Jun 5 '19 at 13:54 # C (gcc), 51 47 bytes f(char**s){for(;*s;printf("\e[s%s\e[u",*s++));}  Try it online! -4 bytes thanks to ceilingcat. Uses the CSI sequences for save/restore cursor position. Just iterates over the passed string array (in the same format as argv) and prints <save position>string<restore position> for each. This does leave the cursor at the top left, so when running at the terminal it is important to leave enough newlines afterwards so that the prompt doesn't clobber the input. # Japt-P, 7 bytes Takes input as an array of multi-line strings, outputs a single multi-line string. ú y_¸¬Ì  Try it ú y_¸¬Ì :Implicit input of array ú :Right pad each line of each element with spaces to the length of the longest y :Transpose _ :Map ¸ : Split on spaces ¬ : Join Ì : Last character :Implicitly join and output  # T-SQL query, 297 295 bytes Using ¶ as separator and a table variable as input. DECLARE @ table(a varchar(max),k int identity(1,1)) INSERT @ values('aaaa¶aaaa¶aaaa¶aaaa'),('bb¶bv¶bb'),('c'); WITH c as(SELECT k,row_number()over(partition by k order by k)s,value v FROM @ CROSS APPLY string_split(a,'¶')s),m(i,l,e)as(SELECT*FROM c WHERE k=1UNION ALL SELECT k,s,STUFF(e,1,len(v),v)FROM m JOIN c ON-~i=k and s=l)SELECT top 1with ties e FROM m ORDER BY rank()over(partition by l order by-i)  Try it online # Javascript (browser), 129 124 bytes My first attempt at code golfing. I read the links given in the rules (loopholes, standard rules...), so I hope I did anything wrong! I kept the inputs as they are in the first post (flat array form). _=o=>{o=o.map(i=>i.split\n),r=o.shift();for(a of o)for(l in a)b=a[l],r[l]=r[l]?b+r[l].slice(b.length):b;return r.join\n}  Thanks to Kevin Cruijssen for saving 5 bytes. Tests: _=o=>{o=o.map(i=>i.split\n),r=o.shift();for(a of o)for(l in a)b=a[l],r[l]=r[l]?b+r[l].slice(b.length):b;return r.join\n} console.log(_(["aaaa\naaaa\naaaa\naaaa","bb\nbb\nbb","c"])); console.log(_(["12345\n54321","00\n00\n00\n00","001\n011\n012"])); console.log(_(["sm\noo\nmr\nee\nt!\nh_\ni_\nn_\ng_","!@#$%^\n&*()_+\nqwerty\nuiopas","this\nis_a\ntest"]));

• Welcome to PPCG! Nice first answer, +1 from me. Some small things to golf: for(a of o){for(l in a){b=a[l],r[l]=(r[l])?b+r[l].slice(b.length):b}} can be for(a of o)for(l in a)b=a[l],r[l]=r[l]?b+r[l].slice(b.length):b; :) – Kevin Cruijssen Jun 12 '19 at 16:11
• @KevinCruijssen - Thanks, I updated my post! I read these two guides before posting, they were both useful. But I possibly miss some tricks that could improve even more my attempt! – Kévin Bibollet Jun 12 '19 at 16:33
• One other thing from my first comment you missed are the parenthesis around the =(r[l])? which can be removed to =r[l]? :) – Kevin Cruijssen Jun 12 '19 at 16:39
• @KévinBibollet, it's needed in order to return the final result of r. Without it, the result of the mapping would be returned instead. – Shaggy Jun 13 '19 at 20:38
• If you want to retain the I/O format used in the test cases, though, you can still get down to 85 bytes but you should note that I/O is flexible. – Shaggy Jun 13 '19 at 20:41

# Pyth, 18 bytes

L.tb0VyQsme #dy #N


Try it online! (note: the code itself evaluates only one block, the interpreter's test suite mode runs the program once for each line of input)

Based on TFeld's Python 2 solution.

Explanation:

L.tb0         # define a lambda function called y which does a transpose, padding with integer 0's
VyQ           # loop over transposed first input line (Q = eval(input()) ) (loop index = N)
s          # concatenate array of strings (implicitly printed)
m         # map over
y #N # transpose of non-falsy values of N
e        # for each item: last element of array
#d     # relevant space at the start! filter with identity function, removes falsy values


for an explanation of why the algorithm itself works, see TFeld's answer.

# Charcoal, 4 bytes

ＦθＰι


Explanation:

Loop over the input-list of multi-line strings:

For(q)
Ｆθ


And print the multi-line string without moving the cursor:

Multiprint(i);
Ｐι