16
\$\begingroup\$

ASCII boxes look like this:

++ +---+ +------+ +---+ +---+
++ | | | | | | | |
 | | | | | | | |
+-+ | | | | | | | |
+-+ | | | | | | +---+
 +---+ | | | |
+--+ | | | | ++
| | | | | | ||
| | +------+ | | ||
+--+ | | ||
 +---+ ||
 ||
 +-----+ ||
+------------+ | | ++
| | | |
| | | |
+------------+ +-----+

Here are some examples of the same ASCII boxes, imploded:

++ +- -+ +- -+ +- -+ +- -+
++ | - | | - - | | - | | - |
 | | | -- | | | | |
+-+ | | | | " | - |
+-+ | - | || | | +- -+
 +- -+ | | | |
+--+ | -- | | | ++
| | | - - | " ||
| | +- -+ | | ||
+--+ | - | | |
 +- -+ | |
 -- ||
 - - +- -+ ||
+- - - -+ | - - | ++
| -- -- | | = |
| -- -- | | - - |
+- - - -+ +- -+
 - -
 --

Here is a link to all of these test case boxes in an easier-to-copy format. The order is all inputs followed by all outputs in the same order.

Your goal is to take an ASCII box as input, and return the imploded box. The rules of implosion are:

  1. "+" never changes; neither do "-" or "|" directly adjacent to "+"
  2. Starting from the corners, the "-" and "|" move inward by one space more than the same character closer to the corner did. If a "-" and "|" would ever move to the same spot, neither moves.
  3. If a "-" and "-" move to the same spot, put a "=" in that spot. If a "|" and "|" move to the same spot, put a " in that spot. These count as two of their respective characters in the same spot moving in opposite directions.
  4. Two "-" or two "|" can move past each other, as seen in the bottom left example.
  5. If the box is skinny enough, it will start expanding outwards in the same way, always moving away from the side it started out part of.
  6. The result should be symmetric across the center line in both the x and y directions (ignoring newlines); this includes spaces, so the result may need to be padded with spaces to satisfy that.

Rule Details:

  1. This is code-golf, so shortest program in bytes wins.
  2. Standard loopholes apply.
  3. You can assume each line ends in a newline character.
  4. The only characters in the input string will be "+", "-", "|", " ", and "\n" (newline), and your output string should follow the same rules, with the addition of "=" and " as possible characters.
  5. You may optionally have a single trailing newline at the end of the last line.
  6. The smallest ASCII box you need to handle is the top-left example. Every ASCII box will have exactly 4 "+"s, exactly at its corners.
  7. You will need to handle boxes of size m x n for any integers m,n such that 2<=m,n<256 (largest possible string size of 255*(255+1))
  8. You can assume you will always get a single valid ASCII box as input.
asked Mar 8, 2016 at 21:33
\$\endgroup\$
6
  • \$\begingroup\$ I think you forgot to add " as possible character in the output on numeral 4 of the Rule Details. Edit: Can we assume the input has no empty lines? \$\endgroup\$ Commented May 27, 2017 at 16:58
  • \$\begingroup\$ That 1x6 example is funky, why does it implode outward? I think one of those || in that example need to be a " or something... \$\endgroup\$ Commented Jun 9, 2017 at 14:32
  • \$\begingroup\$ @carusocomputing same as bottom left example, the walls move through each other (so the box volume is negative) -- rules 4 and 5. \$\endgroup\$ Commented Jun 9, 2017 at 15:45
  • \$\begingroup\$ @Lyth shouldn't there still be a " though? I guess the " only appears on 3-wide or greater? \$\endgroup\$ Commented Jun 9, 2017 at 16:03
  • \$\begingroup\$ @carusocomputing Consider this: Where would the " go? On the left, or on the right side? It can't be both, but it can't be either because the result is symmetrical. \$\endgroup\$ Commented Jun 10, 2017 at 3:03

2 Answers 2

14
+50
\$\begingroup\$

Python 2, (削除) 591 (削除ここまで) (削除) 555 (削除ここまで) (削除) 545 (削除ここまで) (削除) 527 (削除ここまで) (削除) 525 (削除ここまで) (削除) 496 (削除ここまで) (削除) 436 (削除ここまで) (削除) 351 (削除ここまで) (削除) 334 (削除ここまで) (削除) 333 (削除ここまで) 303 bytes

s=input()
w=len(s[0])
h=len(s)
V=max(0,w/2-h)
H=max(0,h/2-w)
p=[[' ']*w]*V
q=[' ']*H
s=[q+k+q for k in p+s+p]
d,c=' -=',' |"'
exec"c,d,V,H,w,h=d,c,H,V,h,w;s=map(list,zip(*s))[::-1]\nfor j in range(h-4):q=s[V+j+2];q[H]=c[q[H]==c[2]];r=H+min(j+1,h-4-j);q[r]=c[1+(q[r]>' ')]\n"*4
for x in s:print''.join(x)

Try it online!

EDIT: My old method first imploded the top and bottom, and then the left and right. Instead, we can implode the top, rotate 90 degrees, and do that 4 times. Also, I was using the user-friendly code, this one requires input be in the form [['+', '-', '-', '-', '-', '-', '+'], ['|', ' ', ' ', ' ', ' ', ' ', '|'], ['|', ' ', ' ', ' ', ' ', ' ', '|'], ['|', ' ', ' ', ' ', ' ', ' ', '|'], ['+', '-', '-', '-', '-', '-', '+']] which is ugly but shorter for the program :P (Thanks to Phoenix for catching that)

Credits to Leaky Nun for the header code in the TIO link used for converting human-readable input into computer-readable input.

-85 bytes thanks to Leaky Nun!
-17 bytes by switching from top-implosion to left-implosion which allows the entire row to be stored into a variable and modified. Thanks to Leaky Nun for the suggestion!
-1 byte by switching things around to remove a space.
-30 bytes thanks to Leaky Nun!

answered May 27, 2017 at 5:35
\$\endgroup\$
14
  • \$\begingroup\$ Assign s[0] and S[0] to variables to save a few bytes \$\endgroup\$ Commented May 27, 2017 at 8:18
  • \$\begingroup\$ @Ilikemydog Oh, right. Thanks! \$\endgroup\$ Commented May 27, 2017 at 15:19
  • \$\begingroup\$ You can replace p=s[0] and P=S[0] with p=z(s[0]) and P=z(S[0]), respectively, and then replace all occurrences of z(p) with p and all z(P) with P to save 18 bytes. \$\endgroup\$ Commented Jun 5, 2017 at 2:25
  • \$\begingroup\$ You can also replace (z(s)-1)/2-p with z(s)/2-.5-p and (p-1)/2-z(s) with p/2-.5-z(s) to save 2 more bytes. \$\endgroup\$ Commented Jun 7, 2017 at 2:55
  • \$\begingroup\$ @R.Kap Oh okay. Thanks for both suggestions! \$\endgroup\$ Commented Jun 7, 2017 at 3:54
1
\$\begingroup\$

C (clang), 693 bytes

New lines added for readability. The first two are required but the rest are not.

#define P B[i][l]
#define m malloc(8)
I(B,h,V,S,J,Z,i,j,l,n,H,W,c,C,a,z,_,L,G,u,N,M)char**B,**Z;char*L,*G,*u;{
V=strlen(B[0]);
S=J=0;
Z=m;
for(i=0,j=h-1;i<h/2+h%2;i++,j--){
for(l=0,n=V-1;l<V/2+V%2;l++,n--){
if(P!=43&&((B[i][l-1]!=43&&i<1)||(B[i-1][l]!=43&&l<1))){
H=P==45;
W=P=='|';
P=B[j][l]=B[i][n]=B[j][n]=32;
if(H){
c=(N=i+l-1)==(M=j-l+1)?61:45;
if(M<0)L=m,sprintf(L,"%*s",V,""),L[l]=L[n]=c,Z[J]=L,J++;
else B[N][l]=B[N][n]=B[M][l]=B[M][n]=c;
}
if(W){
c=(N=l+i-1)==(M=n-i+1)?34:'|';
if(M<0)G=m,sprintf(G,"|%*s%s%*s|",i-n-2,"",B[i],i-n-2,""),B[i]=B[j]=G,S++;
else B[i][N]=B[j][N]=B[i][M]=B[j][M]=c;
}
}
}
}
for(a=-J+1;a<=h+J;u=a<1?Z[-a]:a<=h?B[a-1]:Z[a-h-1],C=S+1-strlen(u)/2,printf("%*s%s\n",C>0?C:0,"",u),a++);
}

Thanks for the great challenge! It was quite tricky but I still had a lot of fun.

This takes the input as command-line arguments and outputs to STDOUT a multi-line string of the imploded box. As always, golfing tips are very much appreciated.

Try it online!

answered Jun 11, 2017 at 7:13
\$\endgroup\$
1
  • \$\begingroup\$ 590 bytes \$\endgroup\$ Commented Jun 28, 2020 at 6:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.