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