24
\$\begingroup\$

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:

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

Additional Notes:

  • 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.

\$\endgroup\$
4
  • 3
    \$\begingroup\$ FYI "exacerbate" means "make a bad thing worse". \$\endgroup\$
    – Paul R
    Jan 8, 2016 at 10:31
  • \$\begingroup\$ @PaulR I believe that was the point \$\endgroup\$
    – cat
    Jan 8, 2016 at 12:32
  • \$\begingroup\$ Oh, OK, evidently whatever the point was it went straight over my head! \$\endgroup\$
    – Paul R
    Jan 8, 2016 at 12:56
  • \$\begingroup\$ 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? \$\endgroup\$ Mar 28, 2016 at 0:01

1 Answer 1

2
+50
\$\begingroup\$

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
   else:i.add(j)
  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.

\$\endgroup\$
1
  • \$\begingroup\$ You get the bounty, because I don't forsee any other answers in <1 day. Thanks for answering, keep golfing! \$\endgroup\$
    – Riker
    Apr 22, 2016 at 1:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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