Task

Your task is to write a program that will output ASCII boxes at the locations specified by the input.

Input

You will be given a list of numbers. The format here is a bit flexible, in that you can use any deliminator you want (e.g. 1,2,3,4, 1 2 3 4, [1,2,3,4]). The list is in groups of 4 and specifies the xywh of each box. The width and height of each box will be at least 2. x and width are left-to-right. y and height are top-to-bottom.

Output

Rendering can be thought of as right to left, with the box on the right drawn first, and every box after that is over it. Trailing spaces are allowed, as well as one trailing newline.

How to handle overlapping boxes

The box on the left of the input is the top box, and nothing will overlap it. Every box after it is rendered only in the space that is not contained in a box already and will not replace the border of a already rendered box.

Style

The style of the boxes are fairly standard, with + used for corners, - used for horizontal lines, and | used for vertical lines.

Examples:

(>>> denotes input)

>>>0 0 11 4 7 2 8 4 3 5 8 3
+---------+
|         |
|         |---+
+---------+   |
       |      |
   +---+------+
   |      |
   +------+


>>>0 3 11 4 7 5 8 4 3 8 8 3 4 0 13 5
    +-----------+
    |           |
    |           |
+---------+     |
|         |-----+
|         |---+
+---------+   |
       |      |
   +---+------+
   |      |
   +------+


>>>0 0 2 2
++
++


>>>2 2 5 3 1 1 7 5 0 0 9 7
+-------+
|+-----+|
||+---+||
|||   |||
||+---+||
|+-----+|
+-------+

>>>0 0 3 3 2 0 3 3
+-+-+
| | |
+-+-+
  • Shouldn't that middle one be 4 0 13 5 rather than 0 4 13 5? – Neil Jan 28 '16 at 22:25
  • 2nd rectangle from bottom in first 2 cases has x=7 (to be consistent with the x=0 rectangles) – Level River St Jan 29 '16 at 2:10
  • 1
    Thanks for noticing, I rarely write answers for my questions, and so all this is by hand... – J Atkin Jan 29 '16 at 2:19
  • @JAtkin I am sorry, I missed that. – Conor O'Brien Jan 29 '16 at 16:15
  • It's fine, I frequently miss stuff when reading as well ;) – J Atkin Jan 29 '16 at 16:18
up vote 4 down vote accepted

APL, 116 bytes

{⎕IO←0⋄K←' '⍴⍨⌽+⌿2 2⍴⌈⌿↑⍵⋄K⊣{x y W H←⍵-⌊.5×⍳4⋄K[Y←y+⍳H;X←x+⍳W]←' '⋄K[Y;A←x+0 W]←'|'⋄K[B←y+0 H;X]←'-'⋄K[B;A]←'+'}¨⌽⍵}

This is a function that takes an array of arrays and returns a character matrix.

Tests:

      t1← (0 0 11 4)(8 2 8 4)(3 5 8 3)
      t2← (0 3 11 4)(8 5 8 4)(3 8 8 3)(4 0 13 5)
      t3← (⊂0 0 2 2)
      t4← (2 2 5 3)(1 1 7 5)(0 0 9 7)
      {⎕IO←0⋄K←' '⍴⍨⌽+⌿2 2⍴⌈⌿↑⍵⋄K⊣{x y W H←⍵-⌊.5×⍳4⋄K[Y←y+⍳H;X←x+⍳W]←' '⋄K[Y;A←x+0 W]←'|'⋄K[B←y+0 H;X]←'-'⋄K[B;A]←'+'}¨⌽⍵} ¨ t1 t2 t3 t4
┌───────────────────┬─────────────────────┬────┬───────────┐
│+---------+        │    +-----------+    │++  │+-------+  │
│|         |        │    |           |    │++  │|+-----+|  │
│|         |----+   │    |           |    │    │||+---+||  │
│+---------+    |   │+---------+     |    │    │|||   |||  │
│        |      |   │|         |-----+    │    │||+---+||  │
│   +----+------+   │|         |----+     │    │|+-----+|  │
│   |      |        │+---------+    |     │    │+-------+  │
│   +------+        │        |      |     │    │           │
│                   │   +----+------+     │    │           │
│                   │   |      |          │    │           │
│                   │   +------+          │    │           │
│                   │                     │    │           │
│                   │                     │    │           │
└───────────────────┴─────────────────────┴────┴───────────┘

Explanation:

  • ⎕IO←0: set the index origin to 0.
  • Create a matrix of the right size:
    • ⌈⌿↑⍵: find the largest values for x, y, w, and h
    • +⌿2 2⍴: x+w and y+h
    • K←' '⍴⍨⌽: make a matrix of x+w*y+h spaces and store it in K.
  • Draw the boxes into it:
    • {...}¨⌽⍵: for each of the boxes, in reverse order,
      • x y W H←⍵-⌊.5×⍳4: assign the coordinates to x, y, W, and H, and subtract 1 from both W and H. (coordinates are exclusive, APL array ranges are inclusive.)
      • K[Y←y+⍳H;X←x+⍳W]←' ': fill the current box with spaces
      • K[Y;A←x+0 W]←'|': draw the vertical sides
      • K[B←y+0 H;X]←'-': draw the horizontal sides
      • K[B;A]←'+': set the edges to '+'
    • K⊣: afterwards, return K.
  • 1
    APL is such a strange looking language to an outsider... – J Atkin Jan 28 '16 at 23:40

ES6, 228 223 217 208 201 198 bytes

Accepts an array of arrays of coordinates and returns a string.

a=>a.reverse().map(([x,y,w,h])=>[...Array(y+h)].map((_,i)=>(s=r[i]||'',r[i]=i<y?s:(s+' '.repeat(x)).slice(0,x)+(c=>c[0]+c[1].repeat(w-2)+c[0])(y-i&&y+h-1-i?'| ':'+-')+s.slice(x+w))),r=[])&&r.join`\n`

Where \n represents a newline character.

Edit: Saved 5 bytes by reversing my conditions. Saved a further 6 bytes by switching from an array of char arrays to an array of strings. Saved a further 9 bytes by introducing a temporary variable. Saved a further 7 bytes by introducing a helper function. Saved a further 3 bytes by undoing a previous saving!

Ruby, 153 143

->n{a=(0..m=3*n.max).map{$b=' '*m}
(*n,x,y,w,h=n 
v=w-2
h.times{|i|a[y+i][x,w]=i%~-h<1??++?-*v+?+:?|+' '*v+?|}
)while n[0]
a.delete($b);puts a}

Ungolfed in test program

f=->n{                                #worst case width when x=w=large number, is max input*2+1
  a=(1..m=3*n.max).map{$b=' '*m}      #find m=max value in input, make an a array of 3*m strings of 3*m spaces 
  (
    *n,x,y,w,h=n                      #extract x,y,w,h from the end of n, save the rest back to n     
    v=w-2                             #internal space in rectangle is w-2  
    h.times{|i|                       #for each row
      a[y+i][x,w]=                    #substitute the relevant characters of the relevant lines of a 
      i%~-h<1?                        #i%~-h = i%(h-1). This is zero (<1) for first and last lines of the rectangle
      ?+ + ?-*v + ?+ :?| + ' '*v +?|  # +--...--+ or |  ...  | as required
    }
  )while n[0]                         #loop until data exhausted (n[0] becomes falsy as it does not exist)
a.delete($b);puts a}                  #delete blank rows ($b is a global variable) and display

SmileBASIC, 128 125 bytes

DEF B A
WHILE LEN(A)H=POP(A)W=POP(A)-2Y=POP(A)X=POP(A)FOR I=0TO H-1LOCATE X,Y+I?"+|"[M];"- "[M]*W;"+|"[M]M=I<H-2NEXT
WEND
END

Screenshots (cropped)

screenshot screenshot screenshot screenshot screenshot

Explanation

DEF B A 'make a function and add 12 bytes :(
 WHILE LEN(A) 'repeat until array is empty
  H=POP(A):W=POP(A)-2 'get width/height
  Y=POP(A):X=POP(A) 'get x/y
  FOR I=0 TO H-1 'draw one row at a time
   LOCATE X,Y+I 'position the cursor
   PRINT "+|"[M]; 'draw left edge
   PRINT "- "[M]*W; 'draw middle
   PRINT "+|"[M] 'draw right edge
   M=I<H-2
  NEXT
 WEND
END

M stores whether it's on the first/last row of the box (0=+--+, 1=| |). On the first pass through the loop, M is 0, and on all others until the last, it's 1.

Pyth, 162 145 bytes

J\+K*h.MZm+@d1@d3Q]*h.MZm+@d0@d2QdD:GHb XKHX@KHGb;V_QDlTR@NTVl3Vl2:+l0b+l1H?|qHtl3qH0\-?|qbtl2qb0\|d)):l0l1J:+l0tl2l1J:l0+l1tl3J:+l0tl2+l1tl3J;jK

You can try it here

Output of test suite:

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

++
++

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

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

Horrible solution! Just waiting for someone to beat it

  • 2
    Your first example puts an extra + in where the boxes share an edge. – Linus Jan 28 '16 at 21:45

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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