Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I arbitrarily compose dyadic functions while bonding one side of their arguments in J?

Tags:

j

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.


1 Answers

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),(<"[email protected])'
   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
like image 134
bob Avatar answered Dec 10 '25 04:12

bob



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!