20
\$\begingroup\$

Your task is to accept as input two "ASCII Art"s, and align each piece of art next to each other horizontally.

For example, say you have two strings, "abc\ndef" and "123\n456". You need to align them horizontally to produce the string "abc123\ndef456". I'm calling this "aligning horizontally" because while the inputs, when printed, look like this:

abc
def

and:

123
456

The output, when printed, will look like this:

abc123
def456

Note how one input is placed next to the other.


Input

  • Input will be strings, and can be as two separate arguments, or as a sequence of strings.

  • The characters in the arts will have decimal codes in the range 32-126 (inclusive).

  • It's fine to support an arbitrary number of arts to align instead of just two (but obviously you must support at least two).

  • You can assume that each art will have the same dimensions, and that they will contain at least one line.

  • You must be able to support at least 100x100 character arts.

  • To align with conventions on the site, the argument order does not matter. It does not matter which art is on the left or right.


Output

  • Output will be the aligned arts as mentioned above, either returned or output to the stdout.

  • Any trailing whitespace in optional.

  • There must be no visual separator between the aligned arts.


Input and output arts must be \n or \r delimited strings. It would be overly trivial to allow 2D-arrays.

Submissions may be functions or full programs.

Test Cases:

"abc\ndef", "123\n456" -> "abc123\ndef456".

"qwertyuiop\n asdfghjkl", "Some other\nTextFiller" -> "qwertyuiopSome other\n asdfghjklTextFiller"

"  *  \n *** \n*****\n *** \n  *  \n", "  +  \n  +  \n+++++\n  +  \n  +  \n" -> "  *    +  \n ***   +  \n*****+++++\n ***   +  \n  *    +  \n"
\$\endgroup\$
18
  • 1
    \$\begingroup\$ Can we use a custom delimiter instead of newlines? i.e. "|" or " "? \$\endgroup\$
    – Riker
    Commented Mar 16, 2018 at 15:30
  • 10
    \$\begingroup\$ I'm gonna say no given that would kind of ruin any art. \$\endgroup\$ Commented Mar 16, 2018 at 15:31
  • \$\begingroup\$ May we use \r instead of \n? \$\endgroup\$
    – Adám
    Commented Mar 16, 2018 at 15:50
  • \$\begingroup\$ @Adám Sure. I'll update the wording. \$\endgroup\$ Commented Mar 16, 2018 at 15:52
  • \$\begingroup\$ Is leading whitespace ok? \$\endgroup\$
    – Adám
    Commented Mar 16, 2018 at 15:53

31 Answers 31

20
\$\begingroup\$

Canvas, 1 byte

×

Try it here!

\$\endgroup\$
7
  • 6
    \$\begingroup\$ Cause who doesn't just have a builtin for this? :P \$\endgroup\$ Commented Mar 16, 2018 at 15:49
  • 5
    \$\begingroup\$ That's not even fair. ;-; \$\endgroup\$ Commented Mar 16, 2018 at 15:52
  • 3
    \$\begingroup\$ @KevinCruijssen On PPCG it's usually allowed to take inputs in whatever order you want, and for a stack-based language the current order makes more sense than reverse. \$\endgroup\$
    – dzaima
    Commented Mar 16, 2018 at 16:43
  • 5
    \$\begingroup\$ @KevinCruijssen although I just remembered that I have a built-in for reverse add, so I'm updating the post :p \$\endgroup\$
    – dzaima
    Commented Mar 16, 2018 at 16:45
  • 3
    \$\begingroup\$ So Canvas has two builtins for this? Ok, why not? \$\endgroup\$ Commented Mar 16, 2018 at 20:11
7
\$\begingroup\$

Haskell, 37 bytes

(unlines.).(.lines).zipWith(++).lines

Try it online!

IO as lists of lines would just be zipWith(++). :P

\$\endgroup\$
6
\$\begingroup\$

Python 2, 59 bytes

lambda y:'\n'.join(map(str.__add__,*map(str.splitlines,y)))

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ It can also be shortened by removing the space. :P \$\endgroup\$ Commented Mar 16, 2018 at 15:27
  • \$\begingroup\$ If you want to input and output lists of lines, as you had before, you can get it down to 30: Try it online! \$\endgroup\$
    – user48543
    Commented Mar 16, 2018 at 15:43
  • \$\begingroup\$ I sat there for like 5 minutes trying to decide if I should allow that. As the Haskell answer shows, it would reduce the challenge down to something much more trivial. I suppose though that the overly trivial solutions just wouldn't be as popular. \$\endgroup\$ Commented Mar 16, 2018 at 16:40
4
\$\begingroup\$

05AB1E, 6 bytes

|¶¡øJ»

Try it online!

Explanation

|        # push all input into a list
 ¶¡      # split on newlines
   ø     # zip
    J    # join the rows to single strings
     »   # merge on newlines
\$\endgroup\$
1
  • \$\begingroup\$ Too bad a space between the two inputs wasn't allowed :(. \$\endgroup\$ Commented Mar 16, 2018 at 16:44
3
\$\begingroup\$

Jelly, 4 bytes

Ỵ€ZY

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Perl 5 -0F, 28 bytes

Includes +2 for the \n argument to -F (it's "code" so it should count)

Give inputs directly after each other on STDIN.

#!/usr/bin/perl -0F\n
say@F[$%++,$_]for@F/2..$#F

Try it online!

\$\endgroup\$
3
\$\begingroup\$

Bash + coreutils, 14

  • 4 bytes saved thanks to @DavidFoerster.
paste -d "" $@

Input is given as two filenames as command-line parameters.

Try it online.

\$\endgroup\$
2
  • \$\begingroup\$ You can save 4 bytes: paste -d "" $@ \$\endgroup\$ Commented Mar 16, 2018 at 20:50
  • \$\begingroup\$ @DavidFoerster Thanks! Weird - I tried that earlier and it didn't work. Edit - I see now - instead of -d "", I tried -d"", which of course is no different to -d \$\endgroup\$ Commented Mar 16, 2018 at 21:38
3
\$\begingroup\$

Perl 6, 27 bytes

{join "\n",[Z~] $_>>.lines}

Try it online!

Works with arbitrary number of arts. IO as list of lists would be just &[Z~].

\$\endgroup\$
2
\$\begingroup\$

APL (Dyalog Unicode), 9 bytesSBCS

Full program. Prompts (STDIN) for any length list of \r-delimited strings. The strings may be ragged and of different widths as long as they have the same number of lines. Prints (STDOUT) resulting ASCII art.

⊃,/⎕FMT¨⎕

Try it online!

 prompt for evaluated input

⎕FMT¨ format (evaluate all control characters and return character matrix) each

,/ combine them horizontally (catenation reduction)

 disclose (because the reduction reduced the rank from 1 to 0)

\$\endgroup\$
2
\$\begingroup\$

Java 8, 100 84 78 bytes

a->b->{for(int i=0;;)System.out.println(a.split("\n")[i]+b.split("\n")[i++]);}

Exits with an ArrayIndexOutOfBoundsException to STDERR after it has printed the result to STDOUT, which is allowed.

-6 bytes thanks to @OlivierGrégoire.

Explanation:

Try it online.

a->b->{                        // Method with two String parameters and no return-type
  for(int i=0;;)               //  Loop over the substrings of the first input
    System.out.println(        //   Print:
     a.split("\n")[i]          //    The substring of the first input
     +b.split("\n")[i++]);}    //    plus the same-indexed substring of the second input
\$\endgroup\$
2
  • 1
    \$\begingroup\$ a->b->{for(int i=0;;)System.out.println(a.split("\n")[i]+b.split("\n")[i++]);} 78 bytes. Nothing is said about not having any extra side-effect. So we could simply count until an exception occurs. \$\endgroup\$ Commented Mar 16, 2018 at 17:07
  • \$\begingroup\$ @OlivierGrégoire Thanks! And exiting with an error to STDERR is indeed allowed after it has printed everything to STDOUT. \$\endgroup\$ Commented Mar 16, 2018 at 17:53
2
\$\begingroup\$

Ruby, 48 bytes

->a,b{$;=$/;a.split.zip(b.split).map(&:join)*$/}

Try it online!

A lambda taking two strings and returning a string. Setting the default split delimiter to newline with $;=$/; doesn't save any bytes, but it makes the rest look a little nicer.

Ruby, 49 bytes (arbitrarily many strings)

->s{s.map{|a|a.split$/}.transpose.map(&:join)*$/}

Try it online!

Just for fun. It turns out we can accept an array of strings at an additional cost of only 1 byte.

\$\endgroup\$
2
\$\begingroup\$

JavaScript (ES6), 51 bytes

f=
(a,b)=>a.replace(/.+/g,a=>a+b.shift(),b=b.split`
`)
;document.write("<pre>"+f("abc\ndef", "123\n456")+"</pre>")

\$\endgroup\$
2
\$\begingroup\$

Wonder, 21 bytes

->#oN.zip#++.-> <>"
"

Usage example:

(->#oN.zip#++.-> <>"
")["abc#ndef" "abc#ndef"]

#n is used instead of \n to denote newlines.

Explanation

Verbose version:

(map #oN) . (zip #con) . (map split "#n")

Split each string in the input array along newlines, zip with string concatenate, and output each item.

\$\endgroup\$
2
\$\begingroup\$

Kotlin, 73 bytes

a,b->a.split("\n").mapIndexed{i,s->s+b.split("\n")[i]}.joinToString("\n")

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Vyxal j, 4 bytes

↵∩vṅ

Try it Online!

\$\endgroup\$
2
\$\begingroup\$

K (ngn/k), 15 14 bytes

"\n"/,'/"\n"\'

Try it online!

-1 byte thanks to ngn

\$\endgroup\$
1
  • 1
    \$\begingroup\$ ,/'+ -> ,'/ \$\endgroup\$
    – ngn
    Commented May 19, 2022 at 16:52
1
\$\begingroup\$

Add++, 24 bytes

L,c10CdVAptA$pG$tBcB@£+n

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C, 96 bytes

#define L(s)for(;*s++>10;)putchar(s[-1]);
i;f(s,t)char*s,*t;{for(;i=!!s[-i];puts("")){L(s)L(t)}}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

JavaScript (ES6), 52 bytes

Takes input in currying syntax (a)(b).

a=>b=>a.split`
`.map((s,i)=>s+b.split`
`[i]).join`
`

Try it online!

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 51 49 bytes

param($a,$b)$a-split"
"|%{$_+($b-split"
")[$i++]}

Try it online!

Takes input as literal strings with newlines. You could also use `n (the newline delimiter in PowerShell, not \n) instead.

We first -split the left input string on newlines, which creates an array, and loop through that |%{...}. Each iteration, we string concatenate with the right input string again split on newlines, indexed and incremented.

Those are left on the pipeline and the implicit Write-Output at completion gives us output as an array of strings, which are printed with newlines between.

\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog Unicode), 22 bytes (Adám's SBCS)

{⊃,/↑¨⍵}'[^\n]+'⎕S'&'¨

Try it online!

\$\endgroup\$
0
1
\$\begingroup\$

Red, 78 bytes

func[a b][b: split b"^/"foreach c split a"^/"[prin c print first b b: next b]]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Bash, 92 bytes

a=();for b;do c=;while IFS= read -r d;do a[c++]+=$d;done<<<"$b";done;printf '%s\n' "${a[@]}"

Try it online!

Ungolfed:

array=()                             # Initialize the array
for argument in "${@}"; do           # Loop over the arguments list
  index='0'                          # Reset the index
  while IFS='' read -r 'line'; do    # Loop over every line of the current argument
    array[index]+="${line}"          # Append the line to its corresponding place
    (( index++ ))                    # Increment the index
  done <<< "${argument}"             # End while loop
done                                 # End for loop
printf '%s\n' "${array[@]}"          # Print array's content

Examples:

$ foo $'abc\ndef' $'123\n456'
abc123
def456

$ foo $'qwertyuiop\n asdfghjkl' $'Some other\nTextFiller'
qwertyuiopSome other
 asdfghjklTextFiller

$ foo \
>   $'  *  \n *** \n*****\n *** \n  *  \n' \
>   $'  +  \n  +  \n+++++\n  +  \n  +  \n'
  *    +  
 ***   +  
*****+++++
 ***   +  
  *    +  


# https://gist.github.com/nxnev/dad0576be7eb2996b860c320c01d0ec5
$ foo "$(< input1)" "$(< input2)" "$(< input3)" > output

I also have a shorter one but it fails if the second read statement returns a non-zero value.

Bash, 55 bytes

while IFS= read -r a;IFS= read b<&3;do echo "$a$b";done

Note: <&3 doesn't seem to work on tio.run

This one uses file descriptors (1 and 3) instead of arguments:

$ foo <<< $'qwertyuiop\n asdfghjkl' 3<<< $'Some other\nTextFiller'
qwertyuiopSome other
 asdfghjklTextFiller
\$\endgroup\$
1
\$\begingroup\$

Charcoal, 8 bytes

PθM⌕θ¶→η

Try it online! Link is to verbose version of code. Explanation:

 θ          First input
P           Print without moving the cursor
    θ       First input
     ¶      Literal newline
   ⌕        Find index
  M   →     Move that many squares right
       η    Implicitly print second input

Add 2 bytes to accept multiple inputs:

FA«PιM⌕ι¶→

Try it online! Link is to verbose version of code. Explanation:

 A          Input
F «         Loop over all entries
   Pι       Print current entry
     M⌕ι¶→  Move to next entry

Add 4 bytes to accept unpadded input:

PθM⌈E⪪θ¶Lι→η

Try it online! Link is to verbose version of code. Explanation:

      θ         First input
       ¶        Literal newline
     ⪪          Split
    E           Map over each string
         ι      Current string
        L       Length
   ⌈            Maximum
  M       →     Move that many squares right
\$\endgroup\$
1
\$\begingroup\$

JavaScript (Node.js), 79 bytes

a=>(b=a.map(x=>x.split`
`))[i=0].map(y=>b.map(z=>c+=z[i],c="")&&++i&&c).join`
`

Try it online!

Supports arbitrary number of ASCII arts joining together rather than just 2 (as in the 2 previous JS answers).

\$\endgroup\$
1
\$\begingroup\$

Clean, 61 bytes

import StdEnv
$a b=flatlines[u++v\\u<-mklines a&v<-mklines b]

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Swift 4, 119 bytes

func f(s:[String])->String{return s[0].split{$0=="\n"}.enumerated().map{$0.1+s[1].split{$0=="\n"}[$0.0]+"\n"}.joined()}

Explanation

func f(s: [String]) -> String {
    return s[0].split{ $0=="\n" }       //splitting the first string after every \n
    .enumerated()                       //create a tuple of offsets and elements
    .map {
        $0.1 +                          //current element
        s[1].split{$0 == "\n"}[$0.0] +  //splitting the second string + indexing
        "\n"                            //new line after every line
     }
     .joined()
}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Julia 1.0, 34 bytes

^,x=split,"\n"
a\b=join(a^x.*b^x,x)

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 43 bytes (41 chars)

Column[StringJoin/@(#~StringSplit~"
")]&

 is an unprintable character in the private use area which represents Transpose in Mathematica.

This function takes input as a list of any number of strings and returns a Column object, which displays in a Mathematica notebook in the required manner (although it doesn't on TIO). For an additional ten bytes, replacing Column[---] with StringRiffle[---," "] will cause an output in the form of a single string. This code can take input of any number of strings with varied-length lines, as long as each string has the same number of lines.


Explanation:

#~StringSplit~ Split the input (implicitly applied to each string in the list)

" " at each newline.

Then, transpose this list of lists of strings

StringJoin/@ and join together each of the sublists.

Column Finally, convert this list of strings to a Column object.

Try it online!

\$\endgroup\$
2
  • \$\begingroup\$ Just out of curiosity, how did you come by my challenge? There's been like four very recent submissions to a challenge I posted 4 years ago. \$\endgroup\$ Commented May 3, 2022 at 15:47
  • \$\begingroup\$ It popped up on the recently answered questions (probably from Steffan's Vyxal answer) and so I decided to do it. \$\endgroup\$
    – Romanp
    Commented May 3, 2022 at 15:49
1
\$\begingroup\$

Japt -R, 8 7 5 bytes

·í+V·

Try it

·í+V·     :Implcict input of strings U & V
·         :Split U on newlines
 í        :Interleave with
   V·     :  V split on newlines
  +       :  Reduce by concatenation
          :Implicit output, joined by newlines
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.