in reply to Find duplicate digits

So there are two rules:
  1. No digit can appear more than twice, and
  2. At least one digit must be duplicated.
So break it down into its cases:
m{ ^ (?= \d\d\d\d $ ) # ensure it's only 4 digits long (?: # first digit is the duplicated one (\d) \1 (?!\1) \d (?!\1) \d | (\d) (?!\2) \d \2 (?!\2) \d | (\d) (?!\3) \d (?!\3) \d \3 # second digit is the duplicated one | (\d) (?!\4) (\d) \5 (?!\4|\5) \d | (\d) (?!\6) (\d) (?!\6|\7) \d \7 # third digit is the duplicated one | (\d) (\d) (?!\8|\9) (\d) \10 ) }x;
Now, that's just atrocious. It can be made a bit more efficient by grouping things together smarter:
m{ ^ (?= \d\d\d\d $ ) # ensure it's only 4 digits long (?: # first digit is the duplicated one (\d) (?: \1 (?!\1) \d (?!\1) \d | (?!\1) \d \1 (?!\1) \d | (?!\1) \d (?!\1) \d \1 ) # second digit is the duplicated one | (\d) (?!\2) (\d) (?: \3 (?!\2|\3) \d | (?!\2|\3) \d \3 ) # third digit is the duplicated one | (\d) (\d) (?!\4|\5) (\d) \6 ) }x;
But we're still stuck with disgusting regexes. So... why use a regex? friedo's got a simple non-regex solution for you. The "pattern" you need to match isn't a pretty one.

Update: you could also use a far simpler regex that makes two passes at the string like so:

m{ ^ (?= \d* (\d) \d* \1 ) (?! \d* \1 \d* \1 \d* \1 ) }x;

Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

Replies are listed 'Best First'.
Re^2: Find duplicate digits
by Anonymous Monk on Feb 15, 2006 at 15:21 UTC
    Thanks for your enlightenment :) I didn't know how to approach the problem...regex was the only thing that came to mind. But, yes, I like friedo's simple solution.
Re^2: Find duplicate digits
by Anonymous Monk on Feb 16, 2006 at 03:13 UTC
    Hi japhy,

    I'm trying to understand your updated regex:

    m{ ^ (?= \d* (\d) \d* \1 ) (?! \d* \1 \d* \1 \d* \1 ) }x;
    Could you explain what's going there? Tia :)
      The regex is anchored to the beginning of the string. The first assertion is a positive look-ahead that says "see if we can find zero or more digits, followed by a particular digit, followed by zero or more digits, and then that particular digit again". That satisfies the "at least one digit must be duplicated" rule. The second assertion is a negative look-ahead that says "make sure we can't match zero or more digits, that particular digit, zero or more digits, that particular digit, and then zero or more digits and that particular digit a THIRD time". This satisfies the "the digit can't appear more than three times" rule.

      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
        Great thanks!

        That solves the mystery partially for me, because I'm always finding it hard to understand regex.