in reply to Re^6: Convert an array of numbers into a range
in thread Convert an array of numbers into a range

Regex problems.

  • Comment on Re^7: Convert an array of numbers into a range

Replies are listed 'Best First'.
Re^8: Convert an array of numbers into a range
by rmocster (Novice) on Sep 29, 2016 at 22:39 UTC
    Is there a way to break the regex into two or three regexes to fix this limit?

      c:\@Work\Perl\monks>perl -wMstrict -le "my $s = join q{,}, 1 .. 40_000; ;; $s =~ s{ \b (\d+) (?{ $1 }) \K (?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) }))+ }{-$2}xmsg; print qq{'$s'}; " '1-9,10-99,100-999,1000-9999,10000-40000' c:\@Work\Perl\monks>perl -wMstrict -le "my $s = join q{,}, 1 .. 150_000; ;; $s =~ s{ \b (\d+) (?{ $1 }) \K (?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) }))+ }{-$2}xmsg; print qq{'$s'}; " Complex regular subexpression recursion limit (32766) exceeded at -e l +ine 1. Complex regular subexpression recursion limit (32766) exceeded at -e l +ine 1. Complex regular subexpression recursion limit (32766) exceeded at -e l +ine 1. '1-9,10-99,100-999,1000-9999,10000-42767,42768-75535,75536-99999,10000 +0-132767,132768-150000' c:\@Work\Perl\monks>perl -wMstrict -le "my $s = join q{,}, 1 .. 150_000; ;; $s =~ s{ \b (\d+) (?{ $1 }) \K (?: (?: , (\d+) \b (??{ ++$^R != $2 || length($1) != length($2) })){1 +,30000} )+ }{-$2}xmsg; print qq{'$s'}; " '1-9,10-99,100-999,1000-9999,10000-99999,100000-150000'

      Updates:
      1. I should have mentioned that all these examples use the  \K regex operator, so they all require Perl version 5.10 or greater.
      2. Changed last two code examples (increased range to 150,000) to make contrast greater.
      3. (2016/10/03) If you can stomach the  \K operator (i.e., you're using Perl version 5.10+), here's a further tweak that speeds things up considerably. The critical enhancement is the use of the  "(?(condition)yes-pattern)" conditional expression (see Extended Patterns in perlre). Some other changes have been made, but they seem immaterial to the speed-up. Old (slower) version:
        c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; print qq{perl version $]}; ;; my $s = join q{,}, 1 .. 1_500_000; ;; my $end_point = qr{ , (\d++) \b (??{ ++$^R != $2 || length($1) != length($2) }) }xms; ;; my $start = time; use re 'eval'; $s =~ s{ \b (\d++) (?{ $1 }) \K (?: $end_point{1,32766})+ }{-$2}xmsg; print qq{'$s'}; printf qq{in %d seconds \n}, time - $start; " perl version 5.010001 '1-9,10-99,100-999,1000-9999,10000-99999,100000-999999,1000000-1500000 +' in 18 seconds
        New (faster) version:
        c:\@Work\Perl\monks>perl -wMstrict -le "use 5.010; ;; print qq{perl version $]}; ;; my $s = join q{,}, 1 .. 1_500_000; ;; my $end_point = qr{ , (\d++) (?(?{ ++$^R != $2 || length($1) != length($2) }) (*F)) }xms; ;; my $start = time; use re 'eval'; $s =~ s{ \b (\d++) (?{ $1 }) \K (?: $end_point{1,32766})+ }{-$2}xmsg; print qq{'$s'}; printf qq{in %d seconds \n}, time - $start; " perl version 5.010001 '1-9,10-99,100-999,1000-9999,10000-99999,100000-999999,1000000-1500000 +' in 3 seconds

      Give a man a fish:  <%-{-{-{-<

        I will try these and report back. Thanks a lot.