I have a dyadic function, call it f
, that consumes a number and an array and outputs another array. For example:
0 f x_0
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
where x_0 =: 1+i.30
.
I want to run this an arbitrary number of times, but feeding the array result of the computation into the next invocation of f
. For example, for 3 (the output array will seem arbitrary, but it's correct):
3 f 2 f 1 f 0 f x_0
2 8 6 9 4 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
I would like a function of the form x g y
, where x
is a number and y
is the starting array, and it will apply g
x
number of times using y
as the initial input.
I've attempted to use suffix \.
for this, but I'm having trouble figuring out how to pass x_0
as the initial list to f
. I don't just need to do 2 f 1 f 0 f
. It seems like I need a function that takes a number, and then chains that many functions together while &
ing the integer argument to f
. This fails, though. For example:
f2 =: 3 & f 2 & f 1 & f 0 & f
f2 x_0
|index error: g1
| f2 x_0
This seems like it's close, but I think I'm misunderstanding something about how &
works (g1
is an internal function that I can share if necessary). I think I want something like: f(2, f(1, f(0, y)))
, and y
is my initial list, but I don't want to have to explicitly call f
.
I poked around some more and made more progress with composition:
f2 =: (2 & f) @ (1 & f) @ (0 & f)
f2 x_0
4 6 2 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
This works, but I'm a bit lost as to how to compose an arbitrary number of functions. How do I compose f
an arbitrary number of times while also bonding its left argument to individual elements of an array of decreasing numbers? I feel like there's a more "intrinsic" J way to do this, but I haven't been able to find anything in the documentation so far.
Thank you, and let me know if you need more information.
Neat question and this is the way that I approached it, but as you work with J you will find there could be other ways.
My solution is:
g=. 4 : '> (f~&.>)/ (<y),(<"0@i.x)'
f=. + NB. + is placeholder for whatever f is
a_0 =. 3
b_0 =. 1 + i. 10
a_0 g b_0
4 5 6 7 8 9 10 11 12 13
To break down the steps:
(<b_0),(<"0 i.a_0) NB. append boxed integers of i. a_0 to boxed b_0
┌────────────────────┬─┬─┬─┐
│1 2 3 4 5 6 7 8 9 10 │0│1│2│
└────────────────────┴─┴─┴─┘
(f~&.>)/ (<b_0),(<"0 i.a_0) NB. arguments of f are reversed and unboxed, f operates and then boxes result and moves to next item
┌───────────────────────┐
│4 5 6 7 8 9 10 11 12 13 │
└───────────────────────┘
> (f~&.>)/ (<b_0),(<"0 i.a_0) NB. result is unboxed
4 5 6 7 8 9 10 11 12 13
In tacit form g looks like this:
gt=. >@:(f~ &.>) / @:((<@]) , |.@:<"0@i.@[)
a_0 gt b_0
4 5 6 7 8 9 10 11 12 13