# Find the length of repeating numbers in a list

a = 4;
primes = Prime[Range[PrimePi[10^(a - 1)] + 1, PrimePi[10^a]]];
d = 1;
Cases[IntegerDigits[primes], {_, d .., _}]


This gets me the list of the numbers from my list of primes that have more than one 1 in a row.

{{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1, 1},
{5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}}


Is there a way to get the length of the repeating digits? For instance, I'd rather get an output of

{3,3,2,2,3,2,2,2,3,2}


My goal is to get the count of the ones with the maximum length.

• Keeping your approach, what about doing: Cases[IntegerDigits[primes], id : {_, d .., _} :> Count[id, 1]]?
– user31159
Commented Oct 21, 2016 at 19:48

I emphasize that the OP wanted the longest sequence of 1s in a row.

Consider

it = {{1, 1, 1, 2, 2, 2, 2, 1, 1}}


Then, xavier's comment gives

Cases[it, id : {_, 1 .., _} :> Count[id, 1]]


{}

Max[Last /@ Tally[#]] & /@ it


{5}

which is incorrect.

## This works:

Max /@ (Length /@ Select[#, MemberQ[#, 1] &] & /@ Split /@ it)


{3}

and on the exemplary

it = {{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1, 1},
{5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}}


gives

{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

If 1 is dominant in all sublists (i.e., for sure the longest subsequence of repeating numbers consists of 1s), like in the case of the last it, this will also work:

Length /@ Last /@ Sort /@ Split /@ it


Using Longest

dat = {{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1,
1, 1}, {5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8,
1, 1, 7}};
fun[lst_, d_] :=
Cases[lst, {___, Longest[x__?(# == d &)], ___} :> Length@{x}]


So, fun[#, 1] &@dat yields:

{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

it={{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1, 1},
{5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}};


now use:

Max[Last /@ Tally[#]] & /@ it


to get

{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}


# MaximalBy + Split + Length + Count

In versions 10.0+, you can use MaximalBy in combination with Split:

list = {{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1, 1},
{5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}};

Composition[Length, First, MaximalBy[Count[#, 1]&], Split] /@ list


{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

Composition[Length, First, MaximalBy[Count[#, 1]&], Split]/@ {{1, 1, 1, 2, 2, 2, 2, 1, 1}}


{3}

list =
{{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1,
1}, {5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}};


Using SequenceCount (new in 10.1) - short, but slow with long lists

SequenceCount[#, {1}] & /@ list


{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

Max[%]


3

Using SequenceCases:

list = {{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1,
1, 1}, {5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8,
1, 1, 7}};

Max[SequenceCases[#, {p : Repeated[1]} :> Length[{p}]]] & /@ list
(*{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}*)


One possibility is to use LongestCommonSubsequence:

longestRepeat[list_] := Length @ LongestCommonSubsequence[
ConstantArray[1, Length[list]],
list
]


On the OP example:

longestRepeat /@ list


{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

If speed is an issue, here is a simple Compile approach:

fc = Compile[{{l, _Integer, 1}},
Module[{best=0, cur=0},
Do[
If[i==1,cur++; best=Max[best,cur], cur=0],
{i,l}
];
best
],
RuntimeAttributes->{Listable}
];


We get the same result as before:

fc[list]


{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}

Let's compare the suggested answers on a larger example:

data = RandomInteger[1, {10^4, 100}];

r1 = longestRepeat /@ data; //AbsoluteTiming
r2 = fc[data]; //AbsoluteTiming
r3 = fun[data, 1]; //AbsoluteTiming
r4 = Max/@(Length/@Select[#,MemberQ[#,1]&]&/@Split/@data); //AbsoluteTiming (* corey979 *)
r5 = Composition[Length,First,MaximalBy[Count[#,1]&],Split]/@data; //AbsoluteTiming (* kglr *)

r1 === r2 === r3 === r4 === r5


{0.308581, Null}

{0.011777, Null}

{66.2261, Null}

{0.506145, Null}

{0.943818, Null}

True

list = {{1, 1, 1, 7}, {2, 1, 1, 1}, {2, 1, 1, 3}, {3, 1, 1, 9}, {4, 1, 1, 1},
{5, 1, 1, 3}, {5, 1, 1, 9}, {6, 1, 1, 3}, {8, 1, 1, 1}, {8, 1, 1, 7}};


Using Split and Cases:

f = Length@First@Cases[{1 ..}]@Split@# &;

f /@ list

(*{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}*)

Max[%]

(*3*)


Or a slower version using Sequenceplit, only for didactic purposes:

f[l_] := Length@First@Cases[{1 ..}]@SequenceSplit[l, s : {x_} /; x != 1 :> s]

f /@ list

(*{3, 3, 2, 2, 3, 2, 2, 2, 3, 2}*)

Max[%]

(*3*)