How can I define a verb in J that applies a different verb alternately to each atom in a list?

StackOverflow https://stackoverflow.com/questions/2988579

  •  24-10-2019
  •  | 
  •  

Question

Imagine I've defined the following name in J:

m =: >: i. 2 4 5

This looks like the following:

 1  2  3  4  5
 6  7  8  9 10
11 12 13 14 15
16 17 18 19 20

21 22 23 24 25
26 27 28 29 30
31 32 33 34 35
36 37 38 39 40

I want to create a monadic verb of rank 1 that applies to each list in this list of lists. It will double (+:) or add 1 (>:) to each alternate item in the list. If we were to apply this verb to the first row, we'd get 2 3 6 5 10.

It's fairly easy to get a list of booleans which alternate with each item, e.g., 0 1 $~{:$ m gives us 0 1 0 1 0. I thought, aha! I'll use something like +:`>: @. followed by some expression, but I could never quite get it to work.

Any suggestions?

UPDATE

The following appears to work, but perhaps it can be refactored into something more elegant by a J pro.

poop =: monad define
    (($ y) $ 0 1 $~{:$ y) ((]+:)`(]>:) @. [)"0 y
)
Was it helpful?

Solution

I would use the oblique verb, with rank 1 (/."1)- so it applies to successive elements of each list in turn.

You can pass a gerund into /. and it applies them in order, extending cyclically.

   +:`>: /."1 m 
 2
 3
 6
 5
10

12
 8
16
10
20

22
13
26
15
30

32
18
36
20
40


42
23
46
25
50

52
28
56
30
60

62
33
66
35
70

72
38
76
40
80

OTHER TIPS

I spent a long time and I looked at it, and I believe that I know why ,@ works to recover the shape of the argument.

The shape of the arguments to the parenthesized phrase is the shape of the argument passed to it on the right, even though the rank is altered by the " conjugate (well, that is what trace called it, I thought it was an adverb). If , were monadic, it would be a ravel, and the result would be a vector or at least of a lower rank than the input, based on adverbs to ravel. That is what happens if you take the conjunction out - you get a vector.

So what I believe is happening is that the conjunction is making , act like a dyadic , which is called an append. The append alters what it is appending to what it is appending to. It is appending to nothing but that thing still has a shape, and so it ends up altering the intermediate vector back to the shape of the input.

Now I'm probably wrong. But $,"0@(+:>:/.)"1 >: i. 2 4 5 -> 2 4 5 1 1` which I thought sort of proved my case.

(,@(+:`>:/.)"1 a) works, but note that ((* 2 1 $~ $)@(+ 0 1 $~ $)"1 a) would also have worked (and is about 20 times faster, on large arrays, in my brief tests).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top