Reverse Engineer Bracket Rectangles

Every programmer knows that rectangles □ are really fun. To exacerbate this fun, these cute and fuzzy diagrams can be transformed into groups of interwoven brackets.

This challenge is the inverse of my previous.

Let's say you have a group of interlocking rectangles like so:

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


• No two +s will ever be adjacent
• No two rectangles will ever share an edge or corner
• There will only ever be at most one vertical edge in each column

The first step is to look at the left-most edge of any rectangle. Assign it one of four bracket types ({[<. I choose [.

   +------------+
|            |
[--+-]     +----+-+
[  | ]     |    | |
[  | ] +---+--+ | |
[  | ] |   |  | | |
[--+-] | +-+--+-+-+-+
|   | | |  | | | |
|   | | |  | | | |
|   | | |  | | | |    +-+
|   +-+-+--+ | | |    | |
|     | |    | | |  +-+-+-+
+-----+-+----+ | |  | | | |
| |      | |  | +-+ |
| +------+ |  |     |
|          |  |     |
+----------+  +-----+


Now look at the second left-most rectangle. Since it overlaps a [ rectangle, it must be of a different type. I choose (.

   (------------)
(            )
[--(-]     +----)-+
[  ( ]     |    ) |
[  ( ] +---+--+ ) |
[  ( ] |   |  | ) |
[--(-] | +-+--+-)-+-+
(   | | |  | ) | |
(   | | |  | ) | |
(   | | |  | ) | |    +-+
(   +-+-+--+ ) | |    | |
(     | |    ) | |  +-+-+-+
(-----+-+----) | |  | | | |
| |      | |  | +-+ |
| +------+ |  |     |
|          |  |     |
+----------+  +-----+


The next left-most rectangle does not intersect with any previous rectangle, but does nest within the previous. I choose to assign it ( again. It is normally a good guess to assign a rectangle the same type as what it is nesting inside if possible, but sometimes backtracking is needed.

   (------------)
(            )
[--(-]     +----)-+
[  ( ]     |    ) |
[  ( ] (---+--) ) |
[  ( ] (   |  ) ) |
[--(-] ( +-+--)-)-+-+
(   ( | |  ) ) | |
(   ( | |  ) ) | |
(   ( | |  ) ) | |    +-+
(   (-+-+--) ) | |    | |
(     | |    ) | |  +-+-+-+
(-----+-+----) | |  | | | |
| |      | |  | +-+ |
| +------+ |  |     |
|          |  |     |
+----------+  +-----+


This next rectangle can be assigned [ again.

   (------------)
(            )
[--(-]     +----)-+
[  ( ]     |    ) |
[  ( ] (---+--) ) |
[  ( ] (   |  ) ) |
[--(-] ( [-+--)-)-+-]
(   ( [ |  ) ) | ]
(   ( [ |  ) ) | ]
(   ( [ |  ) ) | ]    +-+
(   (-[-+--) ) | ]    | |
(     [ |    ) | ]  +-+-+-+
(-----[-+----) | ]  | | | |
[ |      | ]  | +-+ |
[ +------+ ]  |     |
[          ]  |     |
[----------]  +-----+


This next rectangle is kinda fun. It intersects both a ( and a [ rectangle, so I could call it a { rectangle (or < but nobody likes those).

   (------------)
(            )
[--(-]     {----)-}
[  ( ]     {    ) }
[  ( ] (---{--) ) }
[  ( ] (   {  ) ) }
[--(-] ( [-{--)-)-}-]
(   ( [ {  ) ) } ]
(   ( [ {  ) ) } ]
(   ( [ {  ) ) } ]    +-+
(   (-[-{--) ) } ]    | |
(     [ {    ) } ]  +-+-+-+
(-----[-{----) } ]  | | | |
[ {      } ]  | +-+ |
[ {------} ]  |     |
[          ]  |     |
[----------]  +-----+


The last two rectangles aren't that bad. They can be of any two different types.

   (------------)
(            )
[--(-]     {----)-}
[  ( ]     {    ) }
[  ( ] (---{--) ) }
[  ( ] (   {  ) ) }
[--(-] ( [-{--)-)-}-]
(   ( [ {  ) ) } ]
(   ( [ {  ) ) } ]
(   ( [ {  ) ) } ]    {-}
(   (-[-{--) ) } ]    { }
(     [ {    ) } ]  <-{-}->
(-----[-{----) } ]  < { } >
[ {      } ]  < {-} >
[ {------} ]  <     >
[          ]  <     >
[----------]  <----->


Reading off the rectangles, I get [(]([{))}]<{}>. This would be one possible output for the above input. Here's a list of many possible options, not exhaustive:

[(]([{))}]<{}>
<(>(<{))}>{()}
{<}[{(]>)}[<>]
any of the 4! permutations of ([{<, you get the idea...


Input

ASCII-art rectangles, on the assumptions that they are unambiguous (see notes above) and can be properly converted into a string of brackets. You may assume either no trailing spaces or padded to a rectangle, with optional trailing newline. There will be no leading whitespace.

Output

Any one of the valid bracket strings that obeys the intersection restrictions of the rectangles. Other than an optional trailing newline, there should be no other characters than brackets. The main rule is, if two squares intersect, then they should be assigned different bracket types.

Goal

This is code-golf, (lack of) quantity over quality.

• FYI "exacerbate" means "make a bad thing worse". – Paul R Jan 8 '16 at 10:31
• @PaulR I believe that was the point – cat Jan 8 '16 at 12:32
• Oh, OK, evidently whatever the point was it went straight over my head! – Paul R Jan 8 '16 at 12:56
• Can we assume that each rectangle has some height? i.e. it cannot have a + for it's top-left corner, and then (immediately below) the + for it's bottom-left corner? – Tersosauros Mar 28 '16 at 0:01

Python 3, 519 bytes

def c(i):
a,b,c,d={},0,[],{}
for e in map("".join,zip(*i.split("\n"))):
if"+"in e:
f=e.index("+"),e.rindex("+")
if f in a:j=a.pop(f);d[j]=f+(d[j],len(c));c.append(j)
else:a[f]=b;d[b]=len(c);c.append(b);b+=1
g,h={},0
while d:
i={list(d)[0]};
for j,(k,l,m,n)in d.items():
for(o,p,q,r)in(d[v]for v in i):
if not(m>r or n<q or k>p or l<o or(q<m<n<r and o<k>l<p)):break
for j in i:del d[j];g[j]=h
h+=1
s,u=set(),""
for t in c:u+="[{(<]})>"[g[t]+4*(t in s)];s.add(t)
return u


Here's a first attempt at a solution. The algorithm used purely looks at the corners in the diagram, abusing the fact only one vertical line can occur in a column, and therefore the first and last + in a column must be the corners of a rectangle. It then collects all rectangles and performs a naive (and somewhat nondeterministic) search for collisionless groups. I am not sure if this will always find the most optimal solution, but it worked for all examples I tried so far. Alternatively it could be replaced by a brute-force search for the least amount of groups.

Input: a string containing the ascii art. No trailing newline, and all lines must be padded to the same length using spaces. It is also completely fine with you not putting any of the |'s or -'s in there as it just looks at the corners.

As the golfing is quite simple (just whitespace minimalization and variable renaming mostly) it could probably be shorter, but as there are no other answers on this yet I'll leave it like this for now.

• You get the bounty, because I don't forsee any other answers in <1 day. Thanks for answering, keep golfing! – Rɪᴋᴇʀ Apr 22 '16 at 1:53