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