« first day (1983 days earlier)      last day (664 days later) » 

2:59 PM
Hold your horses!
Welcome to APL Quest 2015-2! Today's quest is Longest Streak:
> Write a function that takes a numeric vector and returns the length of the longest streak of positive growth.
@Richard OK, now go for it!
 
{⌈/≢¨⊆⍨1≤¯2-/⍵}
Is not ok.
 
{≢⍉↑⊆⍨2</,⍵}
 
Doesnt work when there is no increment
@rabbitgrowth this one is working!
 
I guess we can assume the argument isn't empty.
@rabbitgrowth While this is clever, it isn't efficient. What can we do about that?
 
Use ⌈/≢¨⊆⍨ like Richard's solution?
 
3:06 PM
That helps a bit, but you still create nested vector of runs.
 
no idea
 
Let's think about it. We are finding the spaces where there's an increase: ⎕←2</1 5 3 4 2 6 7 8
 
@Adám 1 0 1 0 1 1 1
 
Can we somehow find the length of the runs of 1s there?
 
3:09 PM
p.s. why is it you put the ravel , in front of ⍵?
 
Because there's an example case which is a scalar.
How about finding the places where we switch between 0 and 1?
 
@Adám I thought about outer product with 2∧/ but didn't manage to resolve it
 
To make sure we have 0s around all runs of 1s, we can concatenate such edge 0s: ⎕←0,0,⍨2</10 1 5 3 4 2 6 7 8
 
XOR?
 
@Adám 0 0 1 0 1 0 1 1 1 0
 
3:11 PM
Yes sir! ⎕←2≠/0,0,⍨2</10 1 5 3 4 2 6 7 8
 
@Adám 0 1 1 1 1 1 0 0 1
 
Now we just need to compare adjacent indices of 1s: ⎕←⍸2≠/0,0,⍨2</10 1 5 3 4 2 6 7 8
 
@Adám 2 3 4 5 6 9
 
⎕←¯2-/⍸2≠/0,0,⍨2</10 1 5 3 4 2 6 7 8
 
@Adám 1 1 1 1 3
 
3:12 PM
And the maximum is what we're after: ⎕←⌈/¯2-/⍸2≠/0,0,⍨2</10 1 5 3 4 2 6 7 8
 
@Adám 3
 
Ahh that's nice
 
l←?⍨1000 where the largest streak is 5:
{≢⍉↑⊆⍨2</,⍵}l                                    → 2.0E¯5 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{⌈/≢¨⊆⍨2</,⍵}l                                   → 1.7E¯5 | -14% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{1≥≢⍵:0 ⋄ m←2≥/,⍵ ⋄ c←+\~m ⋄ ⌈/c-+\m\+\⍣¯1⊢m/c}l → 6.1E¯6 | -70% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{⌈/¯2-/⍸2≠/0,0,⍨2</,⍵}l                          → 1.8E¯6 | -92% ⎕⎕⎕⎕
 
@Adám fails on 1 10 9 8 7 6 5 4 3 4
 
Oh, because it looks at streaks of 0 too.
 
3:17 PM
{⌈/≢¨⊆⍨2</,⍵}l fails for the same reason as mine. Partition doesn't like zero's
 
So we need to avoid every other length
 
and there must be an increment
 
It isn't Partition that's the problem, but the ⌈/ which returns the identity element. Just insert a 0 or max with that.
Ah, so if we invert the Boolean and find the distances between 1s, we should be OK.
 
{⌈/0,≢¨⊆⍨2</,⍵}
 
0⌈⌈/ is more efficient because 0, has to push the entire array one element to the right.
 
3:20 PM
yes, nice
 
⎕←{1,1,⍨2≥/,⍵}1 10 9 8 7 6 5 4 3 4
 
@Adám 1 0 1 1 1 1 1 1 1 0 1
 
⎕←{¯2-/⍸1,1,⍨2≥/,⍵}1 10 9 8 7 6 5 4 3 4
 
@Adám 2 1 1 1 1 1 1 2
 
⎕←{⌈/¯1+¯2-/⍸1,1,⍨2≥/,⍵}1 10 9 8 7 6 5 4 3 4
 
3:23 PM
@Adám 1
 
looks good Adam
 
@Adám yep that's the sane way to do it
 
How do we explain this, though?
 
it finds the distance between non-increasing runs, and gets the max of that
(⌈/¯1+¯1+⌈/ is a simple obvious optimization)
 
¯1-⌊/2-/
 
3:28 PM
I have to go Adam and others, sorry.
Thanks again
 
No worries, I think we're about done anyway.
 
found this a nice one.
 
@Adám huh, that's actually faster than ¯1+⌈/¯2-/ in 18.2. Equal speed in 18.0 though, which is the more obvious result
 
Significantly?
 
      a←⍳10000
      ]runtime -c '¯1-⌊/2-/a' '¯1+⌈/¯2-/a'

  ¯1-⌊/2-/a  → 3.7E¯6 |    0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
  ¯1+⌈/¯2-/a → 9.1E¯6 | +148% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
 
3:31 PM
Whoa.
 
so someone went through optimizing it for 18.0, but that was reverted to 17.0 speed for 18.2
 
Oh.
 
ah, me two years ago noticed it too :)
 
I can add it to the list of wanted reinstatements of 18.0 optimisations.
Done.
{≢⍉↑⊆⍨2</,⍵}l                                    → 2.0E¯5 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{⌈/≢¨⊆⍨2</,⍵}l                                   → 1.8E¯5 | -12% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{1≥≢⍵:0 ⋄ m←2≥/,⍵ ⋄ c←+\~m ⋄ ⌈/c-+\m\+\⍣¯1⊢m/c}l → 6.1E¯6 | -70% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{¯1+⌈/¯2-/⍸1,1,⍨2≥/,⍵}l                          → 1.7E¯6 | -92% ⎕⎕⎕
{¯1-⌊/2-/⍸1,1,⍨2≥/,⍵}l                           → 1.3E¯6 | -94% ⎕⎕⎕
{¯1+⌈/¯2-/⍸1,1,⍨2≥/,⍵}l → 1.7E¯6 |   0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
{¯1-⌊/2-/⍸1,1,⍨2≥/,⍵}l  → 1.3E¯6 | -24% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
Oh, missing the 0⌈ but doesn't make a huge difference.
 
1,1,⍨ guarantees at least 2 elements, 2-/ reduces that to 1 guaranteed element, and thus you'll never have an empty argument to the final fold, so no 0⌈ is necessary
 
3:42 PM
No, I meant for the {⌈/≢¨⊆⍨2</,⍵}
 
ah
 
Is it worth explaining your solution?
 
my original one is some simplification of the traditional subarray cumulative sum where the array being cumulative-summed is all 1s
 
Ah.
And mine is derived from the traditional lengths of 1s runs.
 
I always forget that that exists..
 
3:52 PM
So, unless @xpqz has something to add, I think we're done here.
 
I am on the hoof today sadly so can’t contribute easily
 
Right, I can see how wouldn't be useful here ;-)
 
4:06 PM
Inverse scan ⍥
Is +\⍣¯1 the same as ⊃,¯2-/⊢?
 
Yeah, something like that.
 
4:52 PM
@rabbitgrowth yeah, except it doesn't error on an empty input, which is primarily the reason I chose it here
 
 
5 hours later…
9:31 PM
I keep forgetting to post earlier. I had this {⌈/0,≢¨⊆⍨0<¯2-/,⍵}
 

« first day (1983 days earlier)      last day (664 days later) »