Here's a fairly direct translation to tacit:

   hd=: 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8
   l1=: ] +. ~:@:(*-.)
   f1edy=: (<:@[ ; ]) (1&{::@[ l1 ])^:(0&{::@[) ~:@]
   2 f1edy hd
1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 0 1
   3 f1edy hd
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1
   4 f1edy hd
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Whether this tacit form is a good idea is, of course, another issue...

Sometimes, explicit is the right way to be.

Thanks,

-- 
Raul

On Wed, Jun 18, 2014 at 4:12 PM, greg heil <[email protected]> wrote:
> Marshall said:
>>> f1 =. (] +. ~:@:(*-.)) ~:
> ...
>>> f2 =. (2&{.)^:(2<#)(<@)/.(;@:) i.@#
>
>>> which isn't exactly pretty, but at least allows you to change the number of 
>>> values you want. It's also much slower than f1:
>
>>i admit the idea it couldn`t be modified for arbitrary numbers has been 
>>bugging me for a while.
>
> but say
>    l1 =. ] +. ~:@:(*-.)
> then an equivalent to f1 can be written
>    f1t=:l1 ~:
>
> checking it with Henrys data
>
>     hd=: 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8
>    h1 hd
> 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 0 1
>
>>Also that form can be submitted to power:
>    f1edy=: 13 : '(y&l1)^:(<:x) ~: y'
> trying it out
>    2 f1edy hd
> 1 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 1 0 1
>    3 f1edy hd
> 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1
>    4 f1edy hd
> 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
>
> But AFAICT there is no tacit version to f1edy ...
>
> greg
> ~krsnadas.org
>
> --
>
> from: Roger Hui <[email protected]>
> to: Programming forum <[email protected]>
> date: 12 June 2014 18:47
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
>> It's clear that f1 could be made faster in C by modifying ~:'s code,
>
>>Indeed.  Since the data d is small range, a small-range algorithm can be 
>>quite a bit faster.  Even a full-range hashing algorithm can be faster.
>
> ~:d           0.0393
> small range   0.0134
> hashing       0.0208
>
> --
>
> from: Marshall Lochbaum <[email protected]>
> to: [email protected]
> date: 12 June 2014 18:15
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
>>This solution is quite elegant--for those who didn't read the link, the verb 
>>is
>
> f3 =. 2 > (i.~ (] - {) /:@/:)
>
>>However, it's about as fast as f2, that is, a bit slow. I'll have to stick 
>>with f1.
>
>>It seems I had forgotten the blazing speed of ~: . It's clear that f1 could 
>>be made faster in C by modifying ~:'s code, but that algorithm is a bit too 
>>involved to write in J. I don't think any other approach will dethrone f1, 
>>although that's an easy thing to be wrong about...
>
> Marshall
>
> --
>
> from: Henry Rich <[email protected]>
> to: [email protected]
> date: 12 June 2014 15:36
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
> I didn't pay attention to the 'fast' part of the question.
>
>>I can't beat f1.  I tried using m} in place, but it just about breaks even 
>>with f1.  If I know the shape of d, and precalculate a vector of zeros of 
>>that length, I can make a small improvement.  It seems that * on booleans, 
>>and word-wide logical operations, are hard to beat.
>
> --
>
> from: Henry Rich <[email protected]>
> to: [email protected]
> date: 12 June 2014 14:56
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
>    (2&{./. i.@#) 3 1 4 1 5 9 2 6 5 3 5 8 9 7 9 3 2 3 8
>  0  9
>  1  3
>  2  0
>  4  8
>  5 12
>  6 16
>  7  0
> 11 18
> 13  0
>
> 0 {"1 original   will select the unique values, and if
> 1 {"1 original
>
> is 0, there was only 1 copy of it.
>
> --
>
> from: 'Pascal Jasmin' via Programming <[email protected]>
> to: "[email protected]" <[email protected]>
> date: 12 June 2014 10:49
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
>>I misunderstood the question, but here is a way of getting the 2nd match of a 
>>list.
>
> ia =. 4 : ' x } y'
>    }.@:I.@:~:@:(~: ia  ] , (1,#) $ _1:) 2 # i.10
> 1 3 5 7 9 11 13 15 17 19
>
> --
>
> from: Roger Hui <[email protected]>
> to: Programming forum <[email protected]>
> date: 12 June 2014 10:26
> subject: Re: [Jprogramming] Get the first two of each item in a list
>
> See http://www.jsoftware.com/jwiki/Essays/Progressive%20Index-Of.  Choose
> items with occurrence counts <: 2 .
>
> --
>
> from: Marshall Lochbaum <[email protected]>
> to: [email protected]
> date: 12 June 2014 10:17
> subject: [Jprogramming] Get the first two of each item in a list
>
>>I came across this problem and was wondering if anyone could come up with a 
>>solution that is both elegant and fast:
>
>>Given a list of positive integers, return a mask (or index list) which 
>>selects the first two of each unique value in the list.
>
>>Of course ~: is the solution if you only want the first value. A fast but 
>>ugly solution using ~: is
>
> f1 =. (] +. ~:@:(*-.)) ~:
>
>>which relies on the fact that the list is always positive. A more general 
>>solution using key, which returns an unordered list of indices, is
>
> f2 =. (2&{.)^:(2<#)(<@)/.(;@:) i.@#
>
>>which isn't exactly pretty, but at least allows you to change the number of 
>>values you want. It's also much slower than f1:
>
>    d =. 99 , 100 + 1e7?.@$10000
>    (I.@:f1 -: /:~@:f2) d
> 1
>    6!:2 'f1 d'
> 0.273576
>    6!:2 'f2 d'
> 1.08829
>
> Any other ideas?
>
> Marshall
> ----------------------------------------------------------------------
> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to