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

Reply via email to