views:

31

answers:

1

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
)
+2  A: 

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
David
That's almost what I need! The only problem is that I need the original shape (2 4 5) back afterwards. Not sure how to do that.
Gregory Higley
I figured it out: ($ m) $ ,^:_ +:`>: /."1 m
Gregory Higley
Actually, I don't even need the power conjunction, so I can just say:($ m) $ , +:`>:/."1 m
Gregory Higley
For reasons which I don't understand, if I say ,@(+:`>:/."1) m it preserves the original shape.
Gregory Higley
I'm not going to pretend I know why that works either. :) That's just the magic of J.
David