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
+-+-+
| | |
+-+-+
5 Answers 5
APL, 116 bytes
{⎕IO←0⋄K←' '⍴⍨⌽+⌿2 2⍴⌈⌿↑⍵⋄K⊣{x y W ×ばつ⍳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 ×ばつ⍳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 to0
.- Create a matrix of the right size:
⌈⌿↑⍵
: find the largest values for x, y, w, and h+⌿2 2⍴
: x+w and y+hK←' '⍴⍨⌽
: make a matrix of x+w*y+h spaces and store it inK
.
- Draw the boxes into it:
{
...} ̈⌽⍵
: for each of the boxes, in reverse order,x y W ×ばつ⍳4
: assign the coordinates tox
,y
,W
, andH
, and subtract 1 from bothW
andH
. (coordinates are exclusive, APL array ranges are inclusive.)K[Y←y+⍳H;X←x+⍳W]←' '
: fill the current box with spacesK[Y;A←x+0 W]←'|'
: draw the vertical sidesK[B←y+0 H;X]←'-'
: draw the horizontal sidesK[B;A]←'+'
: set the edges to '+'
K⊣
: afterwards, returnK
.
-
1\$\begingroup\$ APL is such a strange looking language to an outsider... \$\endgroup\$J Atkin– J Atkin2016年01月28日 23:40:29 +00:00Commented Jan 28, 2016 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.
-
\$\begingroup\$ This is pretty nice :) \$\endgroup\$J Atkin– J Atkin2017年02月02日 02:35:49 +00:00Commented Feb 2, 2017 at 2:35
-
\$\begingroup\$ Meta consensus is that you're not allowed to take input from pre-defined variables. \$\endgroup\$FlipTack– FlipTack2017年02月04日 22:28:57 +00:00Commented Feb 4, 2017 at 22:28
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\$\begingroup\$ Your first example puts an extra + in where the boxes share an edge. \$\endgroup\$Linus– Linus2016年01月28日 21:45:33 +00:00Commented Jan 28, 2016 at 21:45
4 0 13 5
rather than0 4 13 5
? \$\endgroup\$