in reply to Find Length Of Longest Ascending/Descending Sequence

How about

my ($longest) = reduce { length($a) >= length($b) ? $a : $b } / ( [0-9] (?: (?: (?<=0)1 | (?<=1)2 | (?<=2)3 | (?<=3)4 | (?<=4)5 | (?<=5)6 | (?<=6)7 | (?<=7)8 | (?<=8)9 | (?<=9)0 )+ | (?: (?<=0)9 | (?<=1)0 | (?<=2)1 | (?<=3)2 | (?<=4)3 | (?<=5)4 | (?<=6)5 | (?<=7)6 | (?<=8)7 | (?<=9)8 )+ ) ) /xg;

And I thought contiguous would be easier than non-contiguous.

Update: No, that's not right. Endpoints can belong to an ascending and a descending series.

my ($longest) = reduce { length($a) >= length($b) ? $a : $b } / ( [0-9] (?: (?<=0)1 | (?<=1)2 | (?<=2)3 | (?<=3)4 | (?<=4)5 | (?<=5)6 | (?<=6)7 | (?<=7)8 | (?<=8)9 | (?<=9)0 )+ ) /xg, / ( [0-9] (?: (?<=0)9 | (?<=1)0 | (?<=2)1 | (?<=3)2 | (?<=4)3 | (?<=5)4 | (?<=6)5 | (?<=7)6 | (?<=8)7 | (?<=9)8 )+ ) /xg;

Update: This can be simplified if you just want the length of the longest rather than the sequence itself.

my $longest = max map length, / ( (?: 1(?=2) | 2(?=3) | 3(?=4) | 4(?=5) | 5(?=6) | 6(?=7) | 7(?=8) | 8(?=9) | 9(?=0) | 0(?=1) )+ | (?: 1(?=0) | 2(?=1) | 3(?=2) | 4(?=3) | 5(?=4) | 6(?=5) | 7(?=6) | 8(?=7) | 9(?=8) | 0(?=9) )+ ) /xg; if (defined($longest)) { ++$longest; } else { $longest = /[0-9]/ ? 1 : 0; }

Ok, maybe not simpler.

I could save typing by using reverse, but it would be a bit slower.

Replies are listed 'Best First'.
Re^2: Find Length Of Longest Ascending/Descending Sequence
by wind (Priest) on May 09, 2011 at 19:50 UTC

    As far as I can tell, when using a purely regex solution, you pretty much have to keep the scanning for ascending and descending sequences separated. Otherwise overlapping sequences will be missed:

    123xxxx56543

    Capturing in one go will return qw(123 56 543) instead of qw(123 56 6543);

    my $asc = join '|', map {"$_(?=".(($_+1)%10).")"} (0..9); my $dsc = join '|', map {"$_(?=".(($_+9)%10).")"} (0..9); while (<DATA>) { my $longest = max map length, /((?:$asc)+)/g, /((?:$dsc)+)/g; print "$longest\n"; }

    Update: This was in reference to your last solution, as previous ones did take this into account.

      Capturing in one go will return qw(123 56 543) instead of qw(123 56 6543);

      Which isn't a problem when you just want the length. The result is 1 more than the length of the longest capture. That's why I increment $longest at the end.

      ...or rather, that's why I was planning on incrementing $longest at the end. Fixed.

        The result is 1 more than the length of the longest capture.

        Why? If the full string is "123", then the result should be 3. If it's "21234", then the result should be 4. Still need to take overlaps into account even if you just want the length.

        Btw, still have the typo in your last bit of code where you use min instead of max.

        my $longest = min map length,