How do I negate a selector in J lang?

Viewed 145

I am playing with selection. Let's look at the initial example:

rarg=. 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   _1 (<(<0 1),(<0 1)) } ( 4 4 $ rarg)
_1 _1  2  3
_1 _1  6  7
 8  9 10 11
12 13 14 15

Here I want to overwrite block {rows=0,1; columns=0,1}. I can use instead of -1 the block :

   (2 2 $ _1 _2 _3 _4) (<(<0 1),(<0 1)) } ( 4 4 $ rarg)
_1 _2  2  3
_3 _4  6  7
 8  9 10 11
12 13 14 15

If I negate rows and columns choice in selector I end-up with the expected:

   _1 (<(<<0 1),(<<0 1)) } ( 4 4 $ rarg)
 0  1  2  3
 4  5  6  7
 8  9 _1 _1
12 13 _1 _1

So far so good. But let's assume I want to "negate" the selector (<(<0 1),(<0 1)) and have something like this:

   _1 NEGATED_SEL } ( 4 4 $ rarg)
0   1  _1  _1
4   5  _1  _1
_1 _1  _1  _1
_1 _1  _1  _1
  1. Is there a way to achieve that using the above selector?
  2. If yes, what if I would like to specify not -1 but arbitrary values? Thanks a lot in advance!
3 Answers

The "correct" way would be using exclude (<):

(<< 0 1) { i. 4 4
0 1 2 3
4 5 6 7
(<<< 0 1) { i. 4 4
 8  9 10 11
12 13 14 15

But, as @Dan_Bron mentioned, this is not permitted by } as the selection would not be rectangular.

You can still use exclude if you first unravel and then re-ravel your input.

sel =: <(<<0 1),(<<0 1)
r =: i. 4 4

sel { r
 10 11
 14 15

_1 sel } r
  0  1  2  3
  4  5  6  7
  8  9 _1 _1
 12 13 _1 _1

new =: -i. 12

($r) $ new (<<<,sel { r) } ,r
   0  _1 _2 _3
  _4  _5 _6 _7
  _8  _9 10 11
 _10 _11 14 15

For a general input m, you could convert the selection to indices by sel { i. $m:

($m) $ new (<<<,sel { i.$m) } , m

A standard way is using a Composite Item (m}) as Dan Bron said:

    aNEGATED_SEL1=. 1 : 'y=. (*./~ 1 < i. # y)} y ,: m'  NB. adverb, 1st variant
    aNEGATED_SEL2=. 1 : 'y=. (*:/~ 1 < i. # y)} m ,: y'  NB. adverb, 2nd variant
   _1 aNEGATED_SEL1 ( 4 4 $ rarg)
 0  1  2  3
 4  5  6  7
 8  9 _1 _1
12 13 _1 _1
   _1 aNEGATED_SEL2 ( 4 4 $ rarg)
 0  1  2  3
 4  5  6  7
 8  9 _1 _1
12 13 _1 _1

If an overwrite block must vary, it might be supplied as a parameter to a conjunction:

   cNEGATED_SEL=. 2 : 'y=. (*./~ n <: i. # y)} y ,: m'
   _1 cNEGATED_SEL 2 ( 4 4 $ rarg)
 0  1  2  3
 4  5  6  7
 8  9 _1 _1
12 13 _1 _1
   _1 cNEGATED_SEL 3 ( 6 6 $ rarg)
 0  1  2  3  4  5
 6  7  8  9 10 11
12 13 14 15  0  1
 2  3  4 _1 _1 _1
 8  9 10 _1 _1 _1
14 15  0 _1 _1 _1

The form used above (Noun Modifier) forced to incapsulate an adverb (}). A recent J Engine modifications (since J903 beta-r) may allow a form you requested (Noun Modifier }).

Thanks everybody for great hints and answers. The final solution with intermediate steps (for beginner J enthusiasts like myself) to follow

  1. Initial matrix
   r =: 100 + 5 5 $ i.25
   r
100 101 102 103 104
105 106 107 108 109
110 111 112 113 114
115 116 117 118 119
120 121 122 123 124
  1. Selection - we want to update everything besides what selects
   sel =: <(<1 2),(<1 2)
   sel { r
106 107
111 112
  1. Indices the selection affects:
   ,sel { i.$r
6 7 11 12
  1. Indices the selection omits:
   selIxs =: (< (<< (,sel { i.$r)) ) { ,i.$r
0 1 2 3 4 5 8 9 10 13 14 15 16 17 18 19 20 21 22 23 24
  1. Final update (we are flattening the matrix to be updated, use vector like updating (here with -1 elements and previously picked ixs) using } and finally enforce shape of the initial matrix)
   ($r) $ _1 selIxs } ,r
_1  _1  _1 _1 _1
_1 106 107 _1 _1
_1 111 112 _1 _1
_1  _1  _1 _1 _1
_1  _1  _1 _1 _1
Related