in reply to Regexp for alphabetical order match within the string

How about ! /(.).*(??{"[^$1-z]"})/ix?
#!/usr/bin/perl -w use strict; if ($ARGV[0] !~ /(.).*(??{"[^$1-z]"})/ix) { print "alpha\n"; } else { print "non-alpha\n"; } __END__ [sgifford@sglaptop sgifford]$ perl /tmp/t4 abcxz alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 abcda non-alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 aaaaaaab alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 aaaaaaabcccccccz alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 aaaaaaabcccccdccz non-alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 aaaaaaaaaaaaa alpha [sgifford@sglaptop sgifford]$ perl /tmp/t4 abcdefghijklmnopqrstuvwxyz alpha

Replies are listed 'Best First'.
Re: Re: Regexp for alphbetical order match within the string
by Roy Johnson (Monsignor) on Oct 30, 2003 at 21:09 UTC
    Very clever, -10. (I got that on an assignment once.)

    Surprisingly, your expression is not case-insensitive, despite the /i switch. That is because you can end up with character classes like [B-z]. One possible remedy: /(.)(??{"[^lc($1)-z]"})/. (Also note that you don't need the .*).

    The other thing about your regex is that it is about 30 times slower than the other recommendations. Don't even try to benchmark it for more than a few thousand iterations. But it is cool.

    The other solutions are all comparable to each other for performance. My benchmarking code attached.

      Just for grins, this tests about 50% quicker than the substr version in your benchmark.

      sub is_sorted{ my( $str, $p, $x ) = ( lc shift, 0 ); chop$x lt $x and return 0 while $x = substr $str, $p++, 2; 1; };

      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "Think for yourself!" - Abigail
      Hooray!

        Nice work! On my box, it was about 30% faster, and this subtle tweaking is about 25% faster, yet:
        sub improved { my $lstr = lc shift; my ($p, $ntst) = (length($lstr)-1); chop($ntst = substr($lstr, $p, 2)) lt $ntst and return 0 while ($p--); 1; }
        while this very similar model is actually slower
        sub hobbled { my $str = lc shift; my ($p, $x) = (length($str)-1); chop($x) lt $x and return 0 while $x = substr($str, $p--, 2); 1; }
Re: Re: Regexp for alphabetical order match within the string
by Nkuvu (Priest) on Oct 30, 2003 at 20:21 UTC
    Urg. Could you explain that? I'm not following the ??{"[^$1-z]"}) bit.
      OK, here's what perlre(1) says about (??{}):
             ""(??{ code })""
                       WARNING: This extended regular expression fea-
                       ture is considered highly experimental, and may
                       be changed or deleted without notice.  A simpli-
                       fied version of the syntax may be introduced for
                       commonly used idioms.
      
                       This is a "postponed" regular subexpression.
                       The "code" is evaluated at run time, at the
                       moment this subexpression may match.  The result
                       of evaluation is considered as a regular expres-
                       sion and matched as if it were inserted instead
                       of this construct.
      

      So the RE first matches any character $1, followed by zero or more of any character. Then it evaluates the code in the (??{}). This code evaluates to a character class for a character outside of the range [$1-z]---a character earlier in the alphabet.

      If you change the code to print what it's trying, it's clearer what's going on:

      if ($ARGV[0] !~ /(.).*(??{print "Searching for [^$1-z] starting at ",p +os($ARGV[0]),"\n"; "[^$1-z]"})/ix)
      produces
      [sgifford@sglaptop sgifford]$ perl /tmp/t4 abcd Searching for [^a-z] starting at 4 Searching for [^a-z] starting at 3 Searching for [^a-z] starting at 2 Searching for [^a-z] starting at 1 Searching for [^b-z] starting at 4 Searching for [^b-z] starting at 3 Searching for [^b-z] starting at 2 Searching for [^c-z] starting at 4 Searching for [^c-z] starting at 3 Searching for [^d-z] starting at 4 alpha

      Other solutions are more efficient, but the OP asked for an RE. :-)

        Thanks for the explanation.