http://qs321.pair.com?node_id=664335

artist has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I like to create a regexp for a number that matches given condition and combine such multiple regex. Numbers are formed in similar way to MasterMind like game.
Example Number: 1122. Conditions:Total 2 digits in correct place and 1 other digit in wrong place. So once we form the regexp and try to match other numbers, then we can deduce that 1232 is ok, but 2211 is not. I also like to get the next regexp for 3456:1:2 ( Number:3456, CorrectPlace:1, Wrong Place:2) etc and combined with previously obtained regexp(s).
I am not sure, how to start.
Thanks,
--Artist

Replies are listed 'Best First'.
Re: Regexp Creation
by jettero (Monsignor) on Jan 25, 2008 at 19:04 UTC
    I would start by using something other than a regex... Perhaps you could use a for loop instead:
    my ($correct, $incorrect) = 0; for(0 .. length($string)-1) { if( substr($string, $_, 1) eq substr($guess, $_, 1) ) { $correct ++; } else { $incorrect ++; } }

    There's probably 600 ways to do it without regexes, but I think the only way you'll get a regex to work is with (?{ }) embedded code match thingies, and that's voodoo. I'm not saying it can't be done, but the documentation on them suggests you not use them.

    Please see: perlre, for, substr.

    -Paul

Re: Regexp Creation
by kyle (Abbot) on Jan 25, 2008 at 19:04 UTC

    I've read your question three times, and I don't have an answer, but I want to make sure I understand the question.

    The data involved are:

    1. A secret number
    2. A guess at what the secret number is (e.g., 1122)
    3. Some description of how the guess matches the secret number (e.g., two of the digits are in the secret number in the place that they were in the guess, and one of the digits is in the secret number but not in the place that it was in the guess).

    What you want is a regular expression that will match every possible number that the secret number could be, given the data you have.

    Additionally, you want to be able to add (1) another guess, and (2) more data about how that guess matches, and refine the regex further.

    Is that correct?

      Yes, exactly. You have put very nicely in words.

      I have few more ways in mind. Based on the guess, it can generate set of numbers that matches the conditions. Example: (1122:2:1) can give the set: x112,1x12,12x2,122x. Later on I can combine the sets( cross product) to see, which combination works good ( instead of generating a possibly complex regexp)

      --Artist
        (1122:2:1) can give the set: x112,1x12,12x2,122x

        There you have me totally confused. Take the second element from your set, 1x12. The two digits in their correct positions must be the first and last, no? So that means that the 1 in third position must exist in the target string, but at a different position than in the "guess" string.

        Do you see the problem yet?

Re: Regexp Creation
by toolic (Bishop) on Jan 25, 2008 at 19:09 UTC
    I do not use a regex, and I am not sure if this will satisfy all your rules, but this may be something to start with:
    #!/usr/bin/env perl use warnings; use strict; my $num_good = 2; my $num_bad = 1; my $try; my $target; $target = 1122; #$try = 1232; # good $try = 2211; # bad my @digits_targ = split //, $target; my @digits_try = split //, $try; my $cnt_right = 0; my $cnt_wrong = 0; for my $i (0 .. $#digits_targ) { if ($digits_targ[$i] == $digits_try[$i]) { $cnt_right++; } else { $cnt_wrong++; } } #print "cnt_right=$cnt_right\n"; #print "cnt_wrong=$cnt_wrong\n"; if (($cnt_right == $num_good) and ($cnt_wrong >= $num_bad)) { print "good\n"; } else { print "bad\n"; }

    Update: I like jettero's use of length and substr better than my use of split.

      Your logic has slight problem at
      $cnt_wrong >= $num_bad
      According to your code 9922 turns out to be 'good' but it should be 'bad'.
      --Artist