Essays/Boxed Array Display
Model of ":
The display of a boxed array b is a literal array d=:":b such that:
- The rank of d is the greater of 2 or the rank of b .
- Excluding the last two axes, the shape of d matches the shape of b .
- The frame (formed by ┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ │ ─ ) is the same in all the planes.
Boxed array display can be modelled as follows:
boxed =: 32 = 3!:0 mt =: 0 e. $ boxc =: 9!:6 '' tcorn =: 2 0{boxc tint =: 1 10{boxc bcorn =: 8 6{boxc bint =: 7 10{boxc sh =: (*/@}: , {:)@(1&,)@$ ($,) ] rows =: */\.@}:@$ bl =: }.@(,&0)@(+/)@(0&=)@(|/ i.@{.@(,&1)) mask =: 1&,. #&, ,.&0@>:@i.@# mat =: mask@bl@rows { ' ' , sh edge =: ,@(1&,.)@[ }.@# +:@#@[ $ ] left =: edge&(3 9{boxc)@>@(0&{)@[ , "0 1"2 ] right =: edge&(5 9{boxc)@>@(0&{)@[ ,~"0 1"2 ] top =: 1&|.@(tcorn&,)@(edge&tint)@>@(1&{)@[ ,"2 ] bot =: 1&|.@(bcorn&,)@(edge&bint)@>@(1&{)@[ ,"2~ ] perim =: [ top [ bot [ left right topleft=: (4{boxc)&((<0 0)}) @ ((_2{boxc)&,.) @ ((_1{boxc)&,) inside =: 1 1&}. @: ; @: (,.&.>/"1) @: (topleft&.>) take =: {. ' '"_^:mt frame =: [ perim {@[ inside@:(take&.>)"2 ,:^:(1=#@$)@] rc =: (>./@sh&.>) @: (,.@|:"2@:(0&{"1);1&{"1) @: ($&>) thorn1 =: ":`thbox @. boxed thbox =: (rc frame ]) @: (mat@thorn1&.>)
The model is divided into groups of definitions (which are verbs unless indicated otherwise). The first group are utilities:
- boxed 1 if boxed
- mt 1 if empty
- boxc (noun) the box drawing characters ┌ ┬ ┐ ├ ┼ ┤ └ ┴ ┘ │ ─
- tcorn (noun) the characters ┐ ┌
- tint (noun) the characters ┬ ─
- bcorn (noun) the characters ┘ └
- bint (noun) the characters ┴ ─
mat is the main verb of the next group of definitions. The argument is a literal array; the result is a literal matrix image of the array -- a literal table that "looks like" the argument array.
] a =: 2 3 4 $ 'abcdefghijklmnopqrstuvwx' abcd efgh ijkl mnop qrst uvwx mat a abcd efgh ijkl mnop qrst uvwx $a 2 3 4 $ mat a 7 4
perim draws a perimeter around each plane of the right argument: According to the information in the left argument (a result of rc ), perim puts ┐ ┌ ┬ ─ (top), ┘ └ ┴ ─ (bot), ├ │ (left), or ┤ │ (right) at appropriate positions on the perimeter of each plane.
y=: 2 3 $ (i.2 3) ; 'abc' ; (i.4 1) ; (<2 2$'ussr') ; 12 ; <+&.>i.2 2 3 x=: mat@thorn1&.>y $&.> x ┌───┬───┬────┐ │2 5│1 3│4 1 │ ├───┼───┼────┤ │4 4│1 2│11 9│ └───┴───┴────┘ rc x ┌────┬─────┐ │4 11│5 3 9│ └────┴─────┘ { rc x ┌────┬────┬────┐ │4 5 │4 3 │4 9 │ ├────┼────┼────┤ │11 5│11 3│11 9│ └────┴────┴────┘ (2 3;4 5) perim 6 10$'a' ┌────┬─────┐ │aaaaaaaaaa│ │aaaaaaaaaa│ ├aaaaaaaaaa┤ │aaaaaaaaaa│ │aaaaaaaaaa│ │aaaaaaaaaa│ └────┴─────┘
topleft catenates the characters ┼ │ ─ on the top and left edges of a literal table. inside produces the inside (excluding perimeter) of a plane of the display. take is {. if the right argument is non-empty, and is an array of blanks otherwise. frame applies to an array of boxed tabular displays, and computes the overall display. rc computes the number of rows and columns in the display of atoms in a plane.
thbox models the monad ": on a boxed array.
topleft 3 4$'a' ┼──── │aaaa │aaaa │aaaa ] t=: ({rc x) inside@:(take&.>)"2 x 0 1 2│abc│0 3 4 5│ │1 │ │2 │ │3 ─────┼───┼───────── ┌──┐ │12 │┌─┬──┬──┐ │us│ │ ││0│1 │2 │ │sr│ │ │├─┼──┼──┤ └──┘ │ ││3│4 │5 │ │ │└─┴──┴──┘ │ │ │ │┌─┬──┬──┐ │ ││6│7 │8 │ │ │├─┼──┼──┤ │ ││9│10│11│ │ │└─┴──┴──┘ (rc x) perim t ┌─────┬───┬─────────┐ │0 1 2│abc│0 │ │3 4 5│ │1 │ │ │ │2 │ │ │ │3 │ ├─────┼───┼─────────┤ │┌──┐ │12 │┌─┬──┬──┐│ ││us│ │ ││0│1 │2 ││ ││sr│ │ │├─┼──┼──┤│ │└──┘ │ ││3│4 │5 ││ │ │ │└─┴──┴──┘│ │ │ │ │ │ │ │┌─┬──┬──┐│ │ │ ││6│7 │8 ││ │ │ │├─┼──┼──┤│ │ │ ││9│10│11││ │ │ │└─┴──┴──┘│ └─────┴───┴─────────┘ (":y) -: (rc x) perim t 1 (": -: thbox) y 1
A final example on an array with an interesting structure:
5!:2 <'frame' ┌─┬─────┬───────────────────────────────────────────────────────────────────┐ │[│perim│┌───────┬─────────────────────────────┬───────────────────────────┐│ │ │ ││┌─┬─┬─┐│┌───────────────────────┬─┬─┐│┌─────────────────────┬─┬─┐││ │ │ │││{│@│[│││┌──────┬──┬───────────┐│"│2│││┌──┬──┬─────────────┐│@│]│││ │ │ ││└─┴─┴─┘│││inside│@:│┌────┬──┬─┐││ │ ││││,:│^:│┌─┬─┬───────┐││ │ │││ │ │ ││ │││ │ ││take│&.│>│││ │ ││││ │ ││1│=│┌─┬─┬─┐│││ │ │││ │ │ ││ │││ │ │└────┴──┴─┘││ │ ││││ │ ││ │ ││#│@│$││││ │ │││ │ │ ││ ││└──────┴──┴───────────┘│ │ ││││ │ ││ │ │└─┴─┴─┘│││ │ │││ │ │ ││ │└───────────────────────┴─┴─┘│││ │ │└─┴─┴───────┘││ │ │││ │ │ ││ │ ││└──┴──┴─────────────┘│ │ │││ │ │ ││ │ │└─────────────────────┴─┴─┘││ │ │ │└───────┴─────────────────────────────┴───────────────────────────┘│ └─┴─────┴───────────────────────────────────────────────────────────────────┘ (": -: thbox) 5!:2 <'frame' 1
thboxcheck has the same argument and result as thbox , but incorporates checks:
thboxcheck=: 3 : 0 z=. thbox y assert. (#$z) = 2 >. #$y assert. z -:&(_2&}.)&$ y t=. (<0$~_2+#$z){z p=. ({."1 t) e. 0 3 6{boxc q=. ({. t) e. 0 1 2{boxc assert. z -:&((,p+./q)#,)"2 t z )
HTML output
thh y "looks like" ":y but is rendered in HTML. For a boxed array the cells in a plane are vertically and horizontally aligned with the cells in other planes (as they do in ":y).
nmat =: +/&.:<:@(*/\)@}:@$ NB. #@mat nbsp =: [: ; ((<' ') 32}<"0 a.) {~ a. i. ] NB. replace space by pad =: '<br>' $~ 4 * *@[ * - BOXCHARS=: 9!:6 '' NB. box drawing characters SPACER =: '<tr class=spacer><td> </td></tr>',CRLF JARRAYSTYLE=: 0 : 0 <style type="text/css"> .jarray {font-family:monospace;} table.jarray {border-collapse:collapse;} table.jarray td {border:solid black thin; vertical-align:top; padding:0.4em;} table.jarray tr.spacer td {border:none;} </style> ) thh=: 3 : 0 NB. "thorn" (array formatting) producing HTML output JARRAYSTYLE,'<div class=jarray>',(0 thh y),'</div>' : if. (0 e. $y) >: 32=3!:0 y do. NB. y is empty or not boxed nbsp _4}.(,z),x pad #z=. (mat ":y),"1 '<br>' else. NB. y is boxed s=. {."1 (_2{.$t) ($,) t=. ":y NB. s is 1st column in 1st plane in ":y h=. <: 2 -~/\ I. s e. 0 3 6{BOXCHARS NB. height (# lines) in each row z=. h thh&.>"2 ,:^:(0>.2-#$y) y NB. format each atom z=. ('<td>','</td>',~])&.> z NB. bracket each atom z=. <@('<tr>','</tr>',~;)"1 z NB. bracket each row '<table class=jarray>',(;(mask bl rows y){SPACER;,z),'</table>',(_4}.x pad nmat t),CRLF end. )
For example:
thh i.2 2 3 4 thh <"0 i.2 2 3 4 thh 5!:2 <'assert' thh 2 3 4 $ i.&.> i.7 thh 2 2 3 $ (i.&.>i.6),<<2 5$'a efghij'
produce the following outputs:
Collected Definitions
boxed =: 32 = 3!:0 mt =: 0 e. $ boxc =: 9!:6 '' tcorn =: 2 0{boxc tint =: 1 10{boxc bcorn =: 8 6{boxc bint =: 7 10{boxc sh =: (*/@}: , {:)@(1&,)@$ ($,) ] rows =: */\.@}:@$ bl =: }.@(,&0)@(+/)@(0&=)@(|/ i.@{.@(,&1)) mask =: 1&,. #&, ,.&0@>:@i.@# mat =: mask@bl@rows { ' ' , sh edge =: ,@(1&,.)@[ }.@# +:@#@[ $ ] left =: edge&(3 9{boxc)@>@(0&{)@[ , "0 1"2 ] right =: edge&(5 9{boxc)@>@(0&{)@[ ,~"0 1"2 ] top =: 1&|.@(tcorn&,)@(edge&tint)@>@(1&{)@[ ,"2 ] bot =: 1&|.@(bcorn&,)@(edge&bint)@>@(1&{)@[ ,"2~ ] perim =: [ top [ bot [ left right topleft=: (4{boxc)&((<0 0)}) @ ((_2{boxc)&,.) @ ((_1{boxc)&,) inside =: 1 1&}. @: ; @: (,.&.>/"1) @: (topleft&.>) take =: {. ' '"_^:mt frame =: [ perim {@[ inside@:(take&.>)"2 ,:^:(1=#@$)@] rc =: (>./@sh&.>) @: (,.@|:"2@:(0&{"1);1&{"1) @: ($&>) thorn1 =: ":`thbox @. boxed thbox =: (rc frame ]) @: (mat@thorn1&.>) thboxcheck=: 3 : 0 z=. thbox y assert. (#$z) = 2 >. #$y assert. z -:&(_2&}.)&$ y t=. (<0$~_2+#$z){z p=. ({."1 t) e. 0 3 6{boxc q=. ({. t) e. 0 1 2{boxc assert. z -:&((,p+./q)#,)"2 t z ) nmat =: +/&.:<:@(*/\)@}:@$ NB. #@mat nbsp =: [: ; ((<' ') 32}<"0 a.) {~ a. i. ] NB. replace space by pad =: '<br>' $~ 4 * *@[ * - BOXCHARS=: 9!:6 '' NB. box drawing characters SPACER =: '<tr class=spacer><td> </td></tr>',CRLF JARRAYSTYLE=: 0 : 0 <style type="text/css"> .jarray {font-family:monospace;} table.jarray {border-collapse:collapse;} table.jarray td {border:solid black thin; vertical-align:top; padding:0.4em;} table.jarray tr.spacer td {border:none;} </style> ) thh=: 3 : 0 NB. "thorn" (array formatting) producing HTML output JARRAYSTYLE,'<div class=jarray>',(0 thh y),'</div>' : if. (0 e. $y) >: 32=3!:0 y do. NB. y is empty or not boxed nbsp _4}.(,z),x pad #z=. (mat ":y),"1 '<br>' else. NB. y is boxed s=. {."1 (_2{.$t) ($,) t=. ":y NB. s is 1st column in 1st plane in ":y h=. <: 2 -~/\ I. s e. 0 3 6{BOXCHARS NB. height (# lines) in each row z=. h thh&.>"2 ,:^:(0>.2-#$y) y NB. format each atom z=. ('<td>','</td>',~])&.> z NB. bracket each atom z=. <@('<tr>','</tr>',~;)"1 z NB. bracket each row '<table class=jarray>',(;(mask bl rows y){SPACER;,z),'</table>',(_4}.x pad nmat t),CRLF end. )
Contributed by Roger Hui. Substantially the same text for Section 1 previously appeared as Section 6.2 of An Implementation of J, 1992-01-27. thh uses HTML techniques described by Ric Sherlock in the J Forum on 2010-03-30.