> 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

Reply via email to