Fold Some Towels!

I heard somewhere that one thing that technology cannot do yet is fold towels1. So it is now your job to prove that statement false!

Given a string as input, made up of rectangles (towels), like the following, fold each towel in half twice. For example:

+------+    +------+        +--+
|      |    |      |        |  |
|      |    |      |        |  |
|      | -> +------+ ->     +--+
|      |
|      |
|      |
+------+

Notice that when a towel is folded, it is first folded up, then from left to right. You program must mimic this behavior as well. Also notice that in the test cases, the towels stays in the same place, but folded.

Rules:

• Standard methods of input/output.
• Standard loopholes apply.
• Input and output should be as a string.
• Trailing whatevers are okay in output, as long as the towels are in the right place relative to each other.
• You may assume that the length of each side of the towel will always be divisible by 2.
• The towels passed as input will always be rectangular.
• The towels will always be separated-- however, they may be separated by variable amounts.

• , so shortest code wins!

Test cases:

Input:
+------+
|      |
|      |
|      |
|      |
|      |
|      |
+------+
Output:
+--+
|  |
|  |
+--+

Input:
+--+ +--+ +--+
|  | |  | |  |
|  | |  | |  |
+--+ +--+ +--+

Output:
++   ++   ++
++   ++   ++

Input:
+----+
|    |
|    |
|    |
|    | ++
+----+ ++

Output:

+-+
| |
+-+

+

Input:
+--+
+--+     ++
||
||
++
Output:
++
+
+

1: This has been disproved by Geobits and Laikoni. However, I did hear it somewhere.

• Why the downvote? If there is something that can be fixed, please tell me. – Comrade SparklePony Apr 13 '17 at 15:51
• Video of towel folding robot. – Laikoni Apr 13 '17 at 16:30
• @Laikoni it seems like tech CAN do anything :-) – Mr. Xcoder Apr 13 '17 at 16:52
• @LuisMendo Edited, there will always be space between the towels. – Comrade SparklePony Apr 13 '17 at 17:41
• Given towels will always line horizontaly? I mean there won't be any towel under other one? – Dead Possum Apr 14 '17 at 10:09

Retina, 245 bytes

m1+^((.)*(?!\+ )[+|]([- ])*[+|].*¶(?<-2>.)*)([+|][- ]*[+|])
$1$.4$* m+^((.)*) ( *) (.*¶(?<-2>.)*)(?(2)(?!))\|\3\|$1|$3|$4 $3 m+^((.)*)\|( *)\|(?=.*¶(?<-2>.)*(?(2)(?!)) )$1+$.3$*-+
([+|])\1
$1 (?!\+ )([+|])([- ])\2(\2*)\3\1$.3$*$1$3$1

Try it online!

Note: some lines end in spaces. Explanation:

m1+                    Repeatedly search from the beginning of input
^((.)*              Optional indentation
(?!\+ )           Towel does not start with a plus and a space
[+|]([- ])*[+|]   A row of towel
.*¶               Rest of the line
(?<-2>.)*         Some indentation on the next line
)
([+|][- ]*[+|])    Another row of towel
$1$.4$* Replace the second row with blanks Delete every other line of every towel (this works because all towels have even height), m+ Repeatedly search ^((.)*) Optional indentation ( *) Find some space (.*¶ Rest of the line (?<-2>.)*) Matching indentation on the next line (?(2)(?!)) Ensure that the indentation exactly matches \|\3\| Piece of towel$1|$3|$4 $3 Swap the piece into the space above shift all the detached towel pieces up, m+ Repeatedly search ^((.)*) Optional indentation \|( *)\| Piece of towel (?= Followed by .*¶ Rest of the line (?<-2>.)* Matching indentation on the next line (?(2)(?!)) Ensure that the indentation exactly matches ) Nothing on the next line$1+$.3$*-+          Change the piece into a towel bottom

and fix the bottom of the towels, effectively folding them up.

([+|])\1    Match a row of towel of width 2, which is just ++ or ||
$1 Change the first column to a space, which folds it Fold the towels of width 2 to the right. (?!\+ ) Towel does not start with a plus and a space ([+|]) Start with a + or a | ([- ])\2 Then at least two -s or spaces (\2*)\3 Then an even number of -s or spaces \1 Then another + or |$.3$* Replace the left half with spaces$1$3$1      Replace the first character of the right half

Fold the remaining towels to the right.

• I would be interested in a more detailed explanation on how the regex works – Cows quack Apr 14 '17 at 16:31
• @KritixiLithos Something like that, or was there something specific? – Neil Apr 14 '17 at 18:40
• Yes, thank you. And am I correct in assuming that <-2> is a .NET balancing group? – Cows quack Apr 14 '17 at 18:43
• @KritixiLithos It uses them: (?<-2>.)* pops the capture each time, so cannot repeat more times then the (.)* did, while (?(2)(?!)) checks that there are no captures left, so that it repeated the same number of times. – Neil Apr 14 '17 at 19:17

Octave with Image Package, 277 272 bytes

function x=f(x)
[i,j,v]=find(bwlabel(x-32));a=@(w)accumarray(v,w,[],@max);r=-a(-i);R=a(i);s=-a(-j);S=a(j);x(:)=32;for k =1:nnz(r)
u=(r(k)+R(k)-1)/2;v=(s(k)+S(k)+1)/2;p=v:S(k);x(r(k),p)=45;x(u,p)=45;q=r(k):u;x(q,v)=124;x(q,S(k))=124;x(u,[v S(k)])=43;x(r(k),[v S(k)])=43;end

Input and output are 2D char arrays.

Try it online! Or verify all test cases: 1, 2, 3, 4. (Note that endfunction in the test cases is only needed to separate the function from the subsequent code. It is not necessary if the function is saved in its own file.)

Readable version and explanation

function x = f(x)
[i,j,v] = find(bwlabel(x-32)); % make background equal to 0 by subtracting 32.
% Then label each connected component (i.e. towel) with a unique integer
% Then get row indices (i) and column indices (j) of nonzero values (v)
a = @(w)accumarray(v,w,[],@max); % helper function. Gives the maximum of w for
% each group given by an integer label in v
r = -a(-i); % upper coordinate of each towel (minimum row index)
R = a(i); % lower coordinate of each towel (maximum row index)
s = -a(-j); % left coordinate of each towel (minimum column index)
S = a(j); % right coordinate of each towel (maximum column index)
x(:) = 32; % remove all towels: fill x with spaces
for k = 1:nnz(r) % for each original towel: create the new, folded towel
u = (r(k)+R(k)-1)/2; % new lower coordinate
v = s(k)+S(k)+1)/2; % new left coordinate
p = v:S(k); % column indices of horizontal edges
x(r(k),p) = 45; % fill upper horizontal edge with '-'
x(u,p) = 45; % fill lower horizontal edge with '-'
q = r(k):u; % row indices of vertical edges
x(q,v) = 124; % fill left vertical edge with '|'
x(q,S(k)) = 124; % fill right vertical edge with '|'
x(u,[v S(k)]) = 43; % fill lower corners with '+'
x(r(k),[v S(k)]) = 43; % fill upper corners with '+'
end