Automatic box expander

Introduction

Sometimes, my boxes are too small to fit anything in it. I need you to make a box expander! So, what makes a box a box in this challenge.

OOOO
O    O
O    O
O    O
OOOO

The corners of the box are always spaces. The box itself can be made out of the same character. That character can be any printable ASCII character, except a space. So, that's these characters:

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~ The side lengths of the box above are 4, 3. You may assume that the side length is always positive. That means that this is the smallest box you need to handle: # # # # In order to expand a box, you need to increment each side length. Let's go through this, step by step, with the above example. We first take the upper side of the box, which is: OOOO We expand this by one, so we get: OOOOO This is the upper and lower part of the box now. After that, we do the same with the sides on the left and right: O O O Becomes: O O O O Now we reassemble the box, which results into: OOOOO O O O O O O O O OOOOO The task Given a box, expand it by 1. The box can be given in multiple lines, or in an array. Test cases OOOO OOOOO O O > O O OOOO O O OOOOO XXXXXX XXXXXXX X X > X X X X X X XXXXXX X X XXXXXXX ~ ~~ ~ ~ > ~ ~ ~ ~ ~ ~~ This is , so the submission with the least amount of bytes wins! • can the box have a new line before it? Aug 12 '16 at 21:40 • @Riley Yes, that is allowed :). Aug 12 '16 at 21:41 • Can the box be padded with spaces? Aug 13 '16 at 3:54 • @LeakyNun Yes, you may do that. Aug 13 '16 at 8:45 19 Answers Vim, 7 bytes ♥GYPjYp where ♥ is Control-V. The cursor starts on the first non-whitespace character of the first line. ♥G Enter visual block mode and go to bottom of document. YP Duplicate this column. j Move down to the second line of the file. Yp Duplicate this line. • Why not use YP both times for consistency? – Neil Aug 13 '16 at 10:34 • I accidentally hit p while recording the animation, so I stuck with it when transcribing the answer. Does it matter? >_>; – Lynn Aug 13 '16 at 10:37 • I just found the inconsistency odd, but I like your explanation. – Neil Aug 13 '16 at 11:21 • This is exactly the same thing as my V answer, just that I happened to create one-byte mappings for <C-v> G and YP. It kinda makes my language feel cheap. :/ Aug 13 '16 at 13:57 • Hm, control-V shows up as a heart on my phone... ❤ Aug 13 '16 at 17:52 JavaScript (ES6), 5753 52 bytes s=>s.replace(/^.(.)/gm,s="$&$1").replace(/(\n.*)/,s) Explanation: The first regexp duplicates the second column and the second regexp duplicates the second row, thus enlarging the box as desired. Edit: Saved 4 bytes thanks to MartinEnder♦. Python, 49 42 bytes Anonymous lambda: -7 from xnor lambda s:[t[:2]+t[1:]for t in s[:2]+s[1:]] Previous version: D=lambda s:s[:2]+s[1:] lambda s:D(list(map(D,s))) D is a function that duplicates the second item of a sequence. • The idea of re-using the function is clever, but it seems to be shorter to just repeat the code: lambda L:[s[:2]+s[1:]for s in L[:2]+L[1:]]. – xnor Aug 13 '16 at 2:34 • Side note for the previous version: I think map(D,D(s)) would give 43 instead Aug 13 '16 at 8:01 Retina, 20 bytes Byte count assumes ISO 8859-1 encoding. 1¶ ¶$%'¶
%2=.
$&$&

Try it online! (There's several additional lines which enable a test suite where the test cases are separated by two linefeeds.)

1¶
¶$%'¶ 1 is a limit which restricts Retina to apply the substitution only to the first match it finds. matches a single linefeed, so we only need to consider replacing the linefeed at the end of the first line. It is replace with ¶$%'¶, where $%' inserts the entire line following the match (a Retina-specific substitution element). Hence, this duplicates the second line. %2=`.$&$& Here, % is per-line mode, so each line is processed individually, and the lines are joined again afterwards. 2= is also a limit. This one means "apply the substitution only to the second match". The match itself is simple a single character and the substitution duplicates it. Hence, this stage duplicates the second column. Haskell, 24 bytes f(a:b:c)=a:b:b:c f.map f Uses RootTwo's idea of duplicating the second row and column. The map f does this to each row, and the f. then does this to the rows. V, 6 5 bytes yêpjÄ Try it online! This is actually a byte longer than it should be. It should have been: äêjÄ But this has an unknown bug. :( Explanation: yê "yank this colum p "paste what we just yanked j "move down to line 2 Ä "and duplicate this line • What does the other one do? Aug 13 '16 at 3:42 • @ConorO'Brien ä is the duplicate operator (essentially "y" and "p" together in one byte) so äê is "duplicate column" Aug 13 '16 at 3:46 PowerShell v2+, 5753 52 bytes param($n)($n-replace'^.(.)','$&$1')[0,1+1..$n.count]

Slightly similar to Neil's JavaScript answer. The first replace matches the beginning of the line and the next two characters, and replaces them with the first character and second-character-twice. Instead of a second replace, it's swapped out for array-indexing to duplicate the second line. Takes input as an array of strings. The resultant array slices are left on the pipeline and printing is implicit.

Saved 4 bytes thanks to Martin.

Some examples:

PS C:\Tools\Scripts\golfing> .\automatic-box-expander.ps1 ' oooo ','o    o',' oooo '
ooooo
o     o
o     o
ooooo

PS C:\Tools\Scripts\golfing> .\automatic-box-expander.ps1 ' # ','# #',' # '
##
#  #
#  #
##
• @MartinEnder Yes, thank-you, O Wise Regex-Sensei. Aug 12 '16 at 20:39

Brachylog, 28 26 bytes

2 bytes thanks to Fatalize.

{bB,?~c[A:C]hl2,A:Bc.}:1a.

Try it online!

• This is two bytes shorter Aug 13 '16 at 7:15
• @Fatalize I never knew you can do it that way... Aug 13 '16 at 7:24

MATL, 12 bytes

tZy"@:2hSY)!

Input is a 2D char array, with semicolon as row separator. For example, the first test case has input

[' OOOO ';'O    O';' OOOO ']

Try it online! Test cases 1, 2, 3.

Explanation

The code does the following twice: repeat the second row of the array and transpose.

To repeat the second row of an m×n array, the vector [1 2 2 3 ... m] is used as row index. This vector is generated as follows: range [1 2 3 ... m], attach another 2, sort.

t       % Take input implicitly. Duplicate
Zy      % Size of input as a two-element array [r, c]
"       % For each of r and c
@     %   Push r in first iteration (or c in the second)
:     %   Generate range [1 2 3 ... r] (or [1 2 3 ... c])
2hS   %   Append another 2 and sort
Y)    %   Apply as row index
!     %   Transpose
% End for. Display implicitly

L+<b2tbyMy

Try it online!

SED 69 19 (14 + 1 for -r) 15

s/.(.)/&\1/;2p
• Can't you just do /.$$.$$/\0\1;2p?
– Neil
Aug 12 '16 at 22:48
• @Neil I looked all over for that 2p, I figured there was a way to do it, but I couldn't find it. Thanks! Aug 12 '16 at 23:00
• The -r'' part is not needed as long as you add 1 byte for the r flag, thus saving 3 bytes. Also, since you edited your first version of the code, the explanation at the end is now not valid. Sep 3 '16 at 11:06
• @Neil Couldn't believe my eyes when I saw the \0 backreference, since they start at 1. The GNU sed's online manual speaks none of it. However, using & is I think equivalent and shorter. Sep 3 '16 at 11:50
• @seshoumara Ah, those regexp version subtleties... which one uses \0 then?
– Neil
Sep 3 '16 at 16:36

CJam, 14 bytes

q~{~\_@]z}2*N*

Similar to my MATL answer, but repeats the second-last row instead of the second.

Try it online!

Explanation

~               e# Interpret as an array
{      }2*     e# Do this twice
~             e# Dump array contents onto the stack
\            e# Swap top two elements
_           e# Duplicate
@          e# Rotate
]         e# Pack into an array again
z        e# Zip
N*   e# Join by newlines. Implicitly display

K, 15 bytes

2{+x@&1+1=!#x}/

Takes input as a matrix of characters:

b: (" OOOO ";"O    O";" OOOO ")
(" OOOO "
"O    O"
" OOOO ")

Apply a function twice (2{…}/) which gives the transpose (+) of the right argument indexed (x@) by the incremental run-length decode (&) of one plus (1+) a list of the locations equal to 1 (1=) in the range from 0 up to (!) the size of the outer dimension of the right argument (#x).

Step by step,

#b
3
!#b
0 1 2
1=!#b
0 1 0
1+1=!#b
1 2 1
&1+1=!#b
0 1 1 2
b@&1+1=!#b
(" OOOO "
"O    O"
"O    O"
" OOOO ")
+b@&1+1=!#b
(" OO "
"O  O"
"O  O"
"O  O"
"O  O"
" OO ")
2{+x@&1+1=!#x}/b
(" OOOOO "
"O     O"
"O     O"
" OOOOO ")

Try it here with oK.

APL, 17 15 bytes

{⍉⍵⌿⍨1+2=⍳≢⍵}⍣2

Test:

smallbox largebox
┌───┬──────┐
│ # │ OOOO │
│# #│O    O│
│ # │O    O│
│   │O    O│
│   │ OOOO │
└───┴──────┘
{⍉⍵⌿⍨1+2=⍳≢⍵}⍣2 ¨ smallbox largebox
┌────┬───────┐
│ ## │ OOOOO │
│#  #│O     O│
│#  #│O     O│
│ ## │O     O│
│    │O     O│
│    │ OOOOO │
└────┴───────┘

Explanation:

⍣2   run the following function 2 times:
{           }     stretch the box vertically and transpose
⍳≢⍵      indices of rows of box
2=         bit-vector marking the 2nd row
⍵/⍨1+           replicate the 2nd row twice, all other rows once
⍉                transpose
• The APL symbol monadic ⍉ is matrix transpose, which isn't the same thing as rotating by 90 degrees. Aug 13 '16 at 15:03
• @JohnE: of course. I must've been more tired than I thought. Actually rotating by 90 degrees would be ⌽⍉ or ⊖⍉, but in this case it does not matter. Aug 16 '16 at 3:06

ListSharp, 326 bytes

ROWS p=ROWSPLIT a BY ["\r\n"]
ROWS p=GETLINES p [1 TO p LENGTH-1]
ROWS p=p+p+p
STRG o=p
ROWS y=EXTRACT COLLUM FROM p SPLIT BY [""]
ROWS x=EXTRACT COLLUM FROM p SPLIT BY [""]
[FOREACH NUMB IN 1 TO o LENGTH-1 AS i]
ROWS m=COMBINE[m,x] WITH [""]
ROWS m=COMBINE[y,m,y] WITH [""]
SHOW=m

I definitely need to add the nesting of functions, but this works very well

comment if you want an explanation

JavaScript, 160146 141 bytes

s=>{a=s;r="";l=s.split("\n");m=l.length;n=l.length;for(i=0;i<=m;i++){for(j=0;j<=n;j++)r+=!(i%m)&&j%n||i%m&&!(j%n)?a:" ";r+="\n"}return r}

Dyalog APL, 14 bytes

(1 2,1↓⍳)¨∘⍴⌷⊢

(

1 2, {1, 2} prepended to

1↓ one element dropped from

the indices

of each

of

the {row-count, column-count}

indexes into

the argument

E.g. for

XX
X  X
XX

we find the indices; {1, 2, 3} for the rows, and {1, 2, 3, 4} for the columns. Now we drop the initial elements to get {2, 3} and {2, 3, 4}, and then prepend with {1, 2}, giving {1, 2, 2, 3} and {1, 2, 2, 3, 4}. Finally, we use this to select rows and columns, simultaneously doubling row 2 and column 2.

TryAPL online!

Ruby, 46 bytes

->a{a.map{|r|r.insert(2,r)}.insert(2,a)}

Very straighforward solution, taking input as array of lines. I don't like duplicated inserts, so will try to golf it.

C#, 127 124 bytes

s=>{int n=s.Count-1,i=0;s=s[n]=s.Insert(1,s+"");s.Insert(1,s);for(;i++<n;)s[i]=s[i].Insert(1," ");return s;};

Compiles to a Func<List<string>, List<string>>.

Formatted version:

s =>
{
int n = s.Count - 1, i = 0;

s = s[n] = s.Insert(1, s + "");

s.Insert(1, s);

for (; i++ < n;)
s[i] = s[i].Insert(1, " ");

return s;
};