# Introduction

I think everyone agrees that nice pictures have to have a nice frame. But most challenges on this site about ASCII-Art just want the raw picture and don't care about it's preservation.
Wouldn't it be nice if we had a program that takes some ASCII-Art and surrounds it with a nice frame?

# The Challenge

Write a program that takes some ASCII-Art as input and outputs it surrounded by a nice frame.

Example:

*****
***
*
***
*****


becomes

╔═══════╗
║ ***** ║
║  ***  ║
║   *   ║
║  ***  ║
║ ***** ║
╚═══════╝

• You have to use the exact same characters for the frame as in the example: ═ ║ ╔ ╗ ╚ ╝
• The top and the bottom of the frame get inserted before the first and after the last line of the input.
• The left and rights parts of the frame have to have exact one space padding to the widest line of the input.
• There may be no leading or trailing whitespaces in the output. Only a trailing newline is allowed.
• You may assume that the input has no unnecessary leading whitespaces.
• You may assume that the input has no trailing whitespaces on any line.
• You don't have to handle empty input.
• The input will only contain printable ASCII-characters and newlines.

# Rules

Happy Coding!

Using some great ASCII-Art, that was produced in any challenge on this site, as input to your program and showing it with a nice frame is highly encouraged!

• A non-ASCII frame for ASCII art? Heresy! – Dennis Feb 16 '16 at 18:27
• Very closely related. Same challenge, but only using a single (ASCII) character for the frame. – Martin Ender Feb 16 '16 at 18:31
• (I should clarify I don't think it's a dupe. Having to use 6 different characters makes this a lot trickier. The other challenge can be solved by rotating the grid and appending # four times. Adapting such an approach here will be tricky at best, and not viable at worst.) – Martin Ender Feb 16 '16 at 18:38
• @IsmaelMiguel I have won the previous contest and don't see how I could adapt my old answer at all. – Martin Ender Feb 17 '16 at 6:31
• I suspect that DenkerAffe is assuming CP437 or something where the frame chars are also one byte. – Joshua Feb 17 '16 at 18:48

## CJam, 45 chars / 52 bytes

qN/_z,)[_)'═*N]2*C,3%'╔f+.\4/@@f{Se]'║S@2$N}*  Trying to avoid those expensive 3-byte chars was... interesting. Try it online ### Explanation qN/ Split input by newline _z, Zip and get length L, i.e. length of longest line ) Increment -> L+1 [_)'═*N] Make two-element array of "═"*(L+2) and newline 2* Double the array, giving ["═"*(L+2) "\n" "═"*(L+2) "\n"] C, range(12), i.e. [0 1 2 ... 11] 3% Every third element, i.e. [0 3 6 9] '╔f+ Add "╔" to each, giving "╔╗╚╝" .\ Vectorised swap with the previous array, giving ["╔" "═"*(L+2) "╗" "\n" "╚" "═"*(L+2) "╝" "\n"] 4/ Split into chunks of length 4 @@ Move split input and L+1 to top f{...} Map with L+1 as extra parameter... Se] Pad line to length L+1, with spaces '║S Put "║" and space before it 2$N                   Put "║" and newline after it

*                     Join, putting the formatted lines between the top and bottom rows


q=length
g x|l<-lines x,m<-maximum$q<$>l,s<-[-1..m]>>"═"='╔':s++"╗\n"++(l>>= \z->"║ "++z++([q z..m]>>" ")++"║\n")++'╚':s++"╝"


As an example I'm framing snowman "12333321".

*Main> putStrLn $g " _===_\n (O.O)\n/(] [)\\\n ( : )" ╔═════════╗ ║ _===_ ║ ║ (O.O) ║ ║ /(] [)\ ║ ║ ( : ) ║ ╚═════════╝  How it works: bind l: input split into lines m: maximum line length s: m+2 times ═ build top line prepend left frame to each line, pad with spaces, append right frame build bottom line.  ## JavaScript (ES6), 138 bytes This is 138 bytes in the IBM866 encoding, which at time of writing is still supported in Firefox, but 152 in UTF-8. s=>╔${t='═'.repeat(w=2+Math.max(...(a=s.split
).map(s=>s.length)))}╗
${a.map(s=>('║ '+s+' '.repeat(w)).slice(0,w+1)).join║ }║ ╚${t}╝

• Can you actually encode Javascript using CP437 and still run it? If not, then this isn't actually 138 bytes. – Mama Fun Roll Feb 17 '16 at 4:28
• @ӍѲꝆΛҐӍΛПҒЦꝆ Although I couldn't find anything supporting CP437, Firefox currently supports IBM866 which also has these box drawing characters, so I've updated my answer. – Neil Feb 17 '16 at 9:01
• Okay, cool. Have an upvote! – Mama Fun Roll Feb 17 '16 at 14:20

# Bash, 173 171 150 148 147 bytes, 157 136 134 133 characters

q(){((n=${#2}>n?${#2}:n));};mapfile -tc1 -C q v;for((p=++n+1;p;--p));do z+=═;done;echo ╔$z╗;printf "║ %-${n}s║\n" "${v[@]}";echo ╚$z╝


### Multiline:

q() {
(( n = ${#2} > n ?${#2} : n))
}
mapfile -tc1 -C q v

for((p=++n+1;p;--p))
do
z+=═
done

echo ╔$z╗ printf "║ %-${n}s║\n" "${v[@]}" echo ╚$z╝


### Example execution:

bash -c 'q(){((n=${#2}>n?${#2}:n));};mapfile -tc1 -C q v;for((p=++n+1;p;--p));do z+=═;done;echo ╔$z╗;printf "║ %-${n}s║\n" "${v[@]}";echo ╚$z╝'< bear.txt


Sample run from script:

$cat bear2.txt (()__(() / \ ( / \ \ \ o o / (_()_)__/ \ / _,==.____ \ ( |--| ) /\_.|__|'-.__/\_ / ( / \ \ \ ( / ) '._____) / (((____.--(((____/mrf$ ./frame< bear2.txt
╔═══════════════════════╗
║      (()__(()         ║
║      /       \        ║
║     ( /    \  \       ║
║      \ o o    /       ║
║      (_()_)__/ \      ║
║     / _,==.____ \     ║
║    (   |--|      )    ║
║    /\_.|__|'-.__/\_   ║
║   / (        /     \  ║
║   \  \      (      /  ║
║    )  '._____)    /   ║
║ (((____.--(((____/mrf ║
╚═══════════════════════╝

• Your example has an emtpy line between the bottom frame and the input which is invalid. The top and bottom frames have to be inserted directly before and after the input (your previous version was fine btw). – Denker Feb 17 '16 at 8:19
x=length($0) m=m<x?x:m a[NR,1]=x} END{for(;i<m+2;i++)t=t"═" print"╔"t"╗" for(j=1;j<NR;j++){f="║ %-"m"s ║\n" printf f,a[j]}print"╚"t"╝"}  Apparently awk can print Unicode if you can figure out how to get it in the code. • I'm having so many ideas for awesome pipes now ... – Sebb Feb 17 '16 at 23:22 • @Sebb That does seem like fun. :) – Robert Benson Feb 18 '16 at 13:52 # Perl, 111 characters (score includes +5 for the interpreter flags) #!/usr/bin/perl -n0 -aF\n$n=(sort{$b<=>$a}map length,@F)[0];$l="═"x$n;
print"╔═$l═╗\n",(map{sprintf"║ %-${n}s ║\n",$_}@F),"╚═$l═╝";


First, we find the longest line length $n, by numerically sorting the lengths of all lines. We set $l to be the header/footer bar to be n repetitions of the horizontal frame character. Then we print each line formatted to left-align in a field of width n, sandwiched in between the frame characters.

### Result:

╔═══════════╗
║   |\_/|   ║
║  / @ @ \  ║
║ ( > * < ) ║
║  >>x<<'  ║
║  /  O  \  ║
╚═══════════╝


## Pyth, 44 chars (58 bytes)

++\╔K*JhheSlR.z\═\╗jbm+\║+.[+;d;J\║.z++\╚K\╝


Explanation

++\╔K*JhheSlR.z\═\╗                          - print out the first line
lR.z                              -        map(len, all_input())
S                                  -       sorted(^)
e                                   -      ^[-1]
hh                                    -     ^+2
J                                      -    autoassign J = ^
*         \═                            -   ^*"═"
K                                        -  autoassign K = ^
++\╔             \╗                          - imp_print("╔"+^+"╗")

jbm+\║+.[+;d;J\║.z        - print out the middle
jb                        - "\n".join(V)
m             .z        -  [V for d in all_input()]
+\║+       \║          -   "║"+V+"║"
.[   ;J            -    pad(V, " ", J)
+;d              -     " "+d

++\╚K\╝ - print out the end
++\╚K\╝ - imp_print("╚"+K+"╝")


Try it here.

# PHP 5.3, 209 bytes

This only works using the encoding OEM 860. It is an Extended ASCII superset, used in Portuguese DOS versions. Since I'm Portuguese (and I used to love doing these "frames" in Pascal) and this is a standard encoding, I went ahead with this:

<?foreach($W=explode(' ',$argv[1])as$v)$M=max($M,strlen($v)+2);printf("É%'Í{$M}s» º%1${M}sº %2$s º%1${M}sº È%1$'Í{$M}s¼",'',join('
',array_map(function($v)use($M){return str_pad(" $v ",$M);},\$W)));


Here's the base64:

PD9mb3JlYWNoKCRXPWV4cGxvZGUoJwonLCRhcmd2WzFdKWFzJHYpJE09bWF4KCRNLHN0cmxlbigkdikrMik7cHJpbnRmKCLilZQlJ+KVkHskTX1z4pWXCuKVkSUxXCR7JE19c+KVkQolMlwkcwrilZElMVwkeyRNfXPilZEK4pWaJTFcJCfilZB7JE19c+KVnSIsJycsam9pbignCicsYXJyYXlfbWFwKGZ1bmN0aW9uKCR2KXVzZSgkTSl7cmV0dXJuIHN0cl9wYWQoIiAkdiAiLCRNKTt9LCRXKSkpOw==


• Impressive to say the least :) – MonkeyZeus Feb 17 '16 at 21:39
• The codes is 209 bytes/characters. 22+58+11+5+11+24+66+12=209 The last 12 is newlines and as it is DOS that means CRLF, or two bytes per newline. The charactercountonline site does not count newlines. Each of the non-ASCII glyphs are 1 byte in OEM 860. – Runium Feb 17 '16 at 23:39
• @Sukminder Don't forget that (at least) Windows converts \n into \r\n, when opening the file in ASCII/text mode. – Ismael Miguel Feb 17 '16 at 23:43

# Python 3, 119 Bytes

def f(x):
n='\n';s="║ ";e=" ║";h=(x.find(n)+2)*"═";return"╔"+h+"╗"+n+s+x.replace(n,e+n+s)+e+n+"╚"+h+"╝"


126 bytes

import sys
o=["║ %s ║\n"%j[:-1] for j in sys.stdin]
h="═"*(len(o[0])-3)
print("╔"+h+"╗\n"+"".join(o)+"╚"+h+"╝")


Input:

hello
there
!


Output:

╔═══════╗
║ hello ║
║ there ║
║   !   ║
╚═══════╝

• Welcome to Progamming Puzzles & Code Golf! Nice first answer! You can always write functions instead of full programs (unless explicitly forbidden in the challenge) which might allow you to save some bytes by taking the input as argument. Also you might want to use Python 2, so you can save 2 bytes by going with print"╔"+h+"╗\n"+"".join(o)+"╚"+h+"╝". – Denker Feb 19 '16 at 10:49
• Thanks. I couldn't figure out how to get the high-bytes working in Python2 (probably setting the codec environment variable would work but I'm not sure how that plays into golf byte counts). The function approach eliminates python2/3 differences but adds a byte in my best approach. – SumnerHayes Feb 19 '16 at 18:58
• Okay, I got it down to 119 characters as a function; takes input as a string. My mini-markdown is obviously not up to snuff; Line 1 is the def, the rest (after the colon) is line 2, with a leading space. def f(x): n='\n';s="║ ";e=" ║";h=(x.find(n)+2)*"═";return"╔"+h+"╗"+n+s+x.replace(n,e+n+s)+e+n+"╚"+h+"╝" – SumnerHayes Feb 19 '16 at 21:45
• Just update your post with the new version and the new score (struck the old score out with <s>...</s>). Also you can add <!-- language-all: lang-python --> before your code-block to add syntax highlighting to your code. – Denker Feb 19 '16 at 22:33
• This doesn't work if the input is non-rectangular, while the question says that no line will have trailing whitespace. – Dennis Feb 23 '16 at 20:36

# Python 2, 115 Bytes

def f(i):w='═'*(i.find('\n')+2);return'╔%s╗\n║ %s ║\n╚%s╝'%(w,' ║\n║ '.join(i.split('\n')),w)


Looks shorter than 115 here, but working file includes 3-byte UTF-8 BOM mark signature, bumping it up to 115 bytes. If you were to run it in Python 3 you wouldn't need the BOM and it'd get down to 112 bytes.

• Welcome to Programming Puzzles & Code Golf! Unfortunately, your code appears to assume that the input is rectangular, while the question says that no line will have trailing whitespace. – Dennis Feb 23 '16 at 20:33
• I count 107 bytes. I don't think you need to include the "UTF-8 BOM mark signature". – CalculatorFeline Mar 16 '16 at 15:36
• @CatsAreFluffy Are you using Python2? In Python3 all strings are unicode, but it's trickier with Python2. – Jenny Miller Mar 18 '16 at 16:51
• Oops, I counted pipes as 2 bytes, but even after using an actual bytecounter, still only 111 bytes. Tell me where those 5 bytes came from. – CalculatorFeline Mar 18 '16 at 16:57
• The UTF-8 BOM is 3 bytes (en.wikipedia.org/wiki/Byte_order_mark). My count was one high because my text editor was adding a trailing newline, so my solution is really only 115 bytes. You could leave off the leading BOM bytes and get it down to 112 if you were using Python3 (which counts all strings as unicode). But I don't know how you're seeing only 111 bytes. btw, here's how I added the BOM: sed -i '1s/^$$\xef\xbb\xbf$$\?/\xef\xbb\xbf/' codeGolf.py – Jenny Miller Mar 22 '16 at 19:49

# C, 290 bytes

Golfed function B, with dependencies; takes input as null-terminated char*

#define l(s) strlen(s)
p(char*s,int n){while(n--)printf(s);}
B(char*s){char*t=strtok(s,"\n");int x=l(t),z=1;while(t=strtok(0,"\n"))z++,x=l(t)>x?l(t):x;p("╔",1);p("=",x+2);p("╗\n",1);while(z--)printf("║ %s", s),p(" ",x-l(s)),p(" ║\n",1),s+=l(s)+1;p("╚",1);p("=",x+2);p("╝\n",1);}


Somewhat-ungolfed function in full program

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1024

// GOLF-BEGIN =>
#define l(s) strlen(s)
// since multibyte chars don't fit in char: use char* instead
void p (char*s,int n){ while(n--)printf(s); }
void B (char *s){
char *t = strtok(s,"\n");
int x=l(t), z=1;
while(t=strtok(0,"\n"))z++,x=l(t)>x?l(t):x;
// x is l(longest line), z is #lines
p("╔",1);p("=",x+2);p("╗\n",1);
while(z--)printf("║ %s", s),p(" ",x-l(s)),p(" ║\n",1),s+=l(s)+1;
p("╚",1);p("=",x+2);p("╝\n",1);
}
// <= GOLF-END

int main(int argc, char **argv) {
char buffer[MAX];
memset(buffer, 0, MAX);
FILE *f = fopen(argv[1], "rb");
B(buffer);
return 0;
}


input

     _.,----,._
.:'        :.
.'              .
.'                .
:                  :
    .'':''/    '
.   \  |   /   ,'
\   \ |  /   /
\_..,,.._/'
{'-,_'-}
{'-,_'-}
{'-,_'-}
YXXXXY'
~^^~


output

╔======================╗
║      _.,----,._      ║
║    .:'        :.    ║
║  .'              .  ║
║ .'                . ║
║ :                  : ║
║     .'':''/    ' ║
║  .   \  |   /   ,'  ║
║    \   \ |  /   /    ║
║     \_..,,.._/'     ║
║      {'-,_'-}      ║
║      {'-,_'-}      ║
║      {'-,_'-}      ║
║       YXXXXY'       ║
║         ~^^~         ║
╚======================╝
`

C golfing tips appreciated!