Essays/Boxed Array Display

From J Wiki
Jump to navigation Jump to search

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:

Thh.bmp

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.