> From: Sherlock, Ric > Sent: Sunday, 29 August 2010 00:56 > > > From: Alex Gian > > Sent: Sunday, 29 August 2010 00:23 > > > > Oops, before we go any further, I've stumbled on a real gotcha > > e.g. > > > > digits 1974 123 > > 1 9 7 4 > > 0 1 2 3 > > > > now, when I apply (+!) to that lot, it is also applied to the leading > > zero of 0123 - which, of course, leads to a wrong result when summed. > > AAARGH! > > Firstly I tend to build these up bit by bit, making sure I'm getting > what I want as I go. I often end up with a long one-liner that does the > job. If I want to reuse it, or publish it then I might go to the next > step and break it up into component verbs to make it more immediately > readable. > > You want to finish doing digits and (+!) on each number individually > before moving on to the next number for the reason you've shown above. > As Bill suggested earlier, the solution is apply digits at rank 0. > <@(10&#.inv) 1974 123 > +-------+ > |1 9 7 4| > |0 1 2 3| > +-------+ > <@(10&#.inv"0) 1974 123 > +-------+-----+ > |1 9 7 4|1 2 3| > +-------+-----+ > > By default (10&#.inv) will work on the whole right argument at once. > You can check the ranks of the verb as follows: > (10&#.inv) b. 0 > _ _ _ > > You want to modify that to feed each item in the right argument to the > verb separately - hence the "0. > > Box ( < ) as used above is nice for illustrating how this is working > but you want to use (+!) so: > (+!)@(10&#.inv"0) 1974 123 > 2 362889 5047 28 > 2 4 9 0 > > At ( @ ) causes the verb to its left to be fed the results of the verb > to its right each time the verb to the right is "run". In other words > the rank zero is applied to the (+!) too. We could now sum the number > individually too: > +/@(+!)@(10&#.inv"0) 1974 123 > 367966 15 > > Athough this will give the correct answers, it isn't optimal because it > isn't necessary to sum the numbers individually, we will get the same > answer if we wait until all the (+!)@digits"0 operations have completed > and then sum the resulting array and J generally performs better when > operating on large rather than small arrays. We can signal that we want > to wait by using the modified form of At ( @: ). IOW the following is > likely to be faster: > +/@:(+!)@(10&#.inv"0) 1974 123 > 367966 15
I should have thought about this more (and tested) before posting. Although the basic idea is correct - better to make J work on big arrays rather lots of small ones - in this case it doesn't work as I suggest above. To get the effect I intended I would need another set of parentheses and this would highlight that we don't get the desired result: +/@:((+!)@(10&#.inv"0)) 1974 123 4 362893 5056 28 This is the same as +/ (+!)@(10&#.inv"0) 1974 123 4 362893 5056 28 What we want is the sum of the rows which is: +/"1 (+!)@(10&#.inv"0) 1974 123 367966 15 Some will find it "nicer" to incorporate this into the tacit verb using Cap ( [: ) (#~ ] = [: +/"1 (+!)@(10&#.inv"0)) 1974 123 85837 85837 rather than At ( @: ): (#~ ] = +/"1@:((+!)@(10&#.inv"0))) 1974 123 85837 85837 ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
