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

I got this error.

Complex regular subexpression recursion limit (32766) exceeded

s/\b(\d+)(?{$1})\K(?:,(\d+)\b(??{++$^R!=$2||length$1!=length$2}))+/-$2 +/g;

Replies are listed 'Best First'.
Re^7: Convert an array of numbers into a range
by Anonymous Monk on Aug 27, 2016 at 09: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:  <%-{-{-{-<