Finding largest Range in a list

If speed is important, I think that this is a typical example in which compilation of a straightforward algorithm gives better results than making use of the advanced functions of Mathematica. Here is such a compiled function:

f= Compile[{{lst, _Integer, 1}}, Module[{result=0,counting=0},
  Do[ 
    If[n==counting+1,
      counting=n,
      If[counting>result, result=counting]; counting=If[n==1, 1, 0] ],
  {n, lst}];
  Max[{result, counting}]]]

On my computer, for a list of 10^6 positive integers, this function is more than 20 times faster than the splitting technique:

SeedRandom[42];
list=RandomInteger[{1,10},10^6];
Select[Split[list,#1+1==#2&],#[[1]]==1&]//Max // Timing
f[list] // Timing
fC[list] // Timing

(* {2.418016,5} *)
(* {0.109201,5} *)
(* {0.015600,5} *)

Here the function fC is identical to f, but compiled with the option CompilationTarget->"C". So when available, this gives another factor about 9.


This seems to be substantially faster.

extend[list_List, pos_List /; Length[pos] > 0, depth_Integer] := 
 extend[list, 
  pos[[Flatten[
      Position[list[[DeleteCases[Flatten[pos], Length[list]] + 1]], 
       depth + 1]]]] + 1, depth + 1]

extend[list_List, {}, depth_Integer] := depth - 1

extend[list, Position[list, 1], 1]

Also, using Max gives negative infinity when there is no element 1 in the list.

This seems analogous to Boyer-Moore. Therefore, a further improvement would be to extend the first matching substring as much as possible (let's say the length of the substring is n), and then at the second matching substring check to see if it could be longer (by checking the element n positions after the start of the second matching substring), etc.


SeedRandom[42];
list = RandomInteger[{1, 7}, 1000];
Select[Split[list, #1 + 1 == #2 &], #[[1]] == 1 &] // Max
(* 3*)