17
\$\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.
\$\endgroup\$
  • \$\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\$ – Theraot May 27 '17 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\$ – Magic Octopus Urn Jun 9 '17 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\$ – Lyth Jun 9 '17 at 15:45
  • \$\begingroup\$ @Lyth shouldn't there still be a " though? I guess the " only appears on 3-wide or greater? \$\endgroup\$ – Magic Octopus Urn Jun 9 '17 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\$ – HyperNeutrino Jun 10 '17 at 3:03
15
+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!

\$\endgroup\$
  • \$\begingroup\$ Assign s[0] and S[0] to variables to save a few bytes \$\endgroup\$ – caird coinheringaahing May 27 '17 at 8:18
  • \$\begingroup\$ @Ilikemydog Oh, right. Thanks! \$\endgroup\$ – HyperNeutrino May 27 '17 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\$ – R. Kap Jun 5 '17 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\$ – R. Kap Jun 7 '17 at 2:55
  • \$\begingroup\$ @R.Kap Oh okay. Thanks for both suggestions! \$\endgroup\$ – HyperNeutrino Jun 7 '17 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!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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