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

I am trying to increment a string matching /[A-Z][A-Z0-9]+/ but cannot use the ++ operator, since the last character could be A-Z. My needs are to make sure I haven't seen this string before, and keep the first character the same. Is there a way to convert to a number, increment, and convert back to a string?

Here is what I have so far, that I know doesn't work:

+101 $used{"FOO123Z"} = 1; ..snip.. +323 my $new="FOO123Z"; +324 my $len = length($new); +325 while ( defined $used{$new} && $len > 0 ){ ## Keep the +first character the same +326 foreach my $c (("A" .. "Z"), 0..9){ +327 $new =~ s/(.{$len}).(.*)/${1}${c}${2}/ if defined $u +sed{$new}; +328 } +329 $len-- if defined $used{$new} ; +330 } +331 $used{$new} = 1;

Replies are listed 'Best First'.
Re: Increment a mixed alphanumeric (Updated)
by BrowserUk (Patriarch) on Oct 27, 2015 at 14:18 UTC

    So, what should FOO123Z increment to? Showing a sequence of increments would be good.

    Does this come close to your intent?:

    #! perl -slw use strict; my $id = "F00123Z"; for ( 1 .. 11 ) { print $id; substr( $id, 1, -1 )++; } __END__ C:\test>junk72 F00123Z F00124Z F00125Z F00126Z F00127Z F00128Z F00129Z F00130Z F00131Z F00132Z F00133Z

    Update: Or maybe this comes closer?:

    #! perl -slw use strict; my $id = "F00123Z"; for ( 1 .. 29 ) { print $id; if( substr( $id, -1 ) eq 'Z' ) { substr( $id, -1 ) = 'A'; substr( $id, 1, -1 )++; } else { substr( $id, -1 ) ++; } } __END__ C:\test>junk72 F00123Z F00124A F00124B F00124C F00124D F00124E F00124F F00124G F00124H F00124I F00124J F00124K F00124L F00124M F00124N F00124O F00124P F00124Q F00124R F00124S F00124T F00124U F00124V F00124W F00124X F00124Y F00124Z F00125A F00125B

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Right, here is a regexp for valid formats:
      /^[A-Z]+[0-9]*[A-Z]*/;
      N1234Z becomes N12350
      N12359 becomes N1235A
      N9999Z becomes NA0000

      Ordering of the addition is less important than testing all possible variations. Technically NA0000 is invalid since it has a number, but the number part equals zero. I can handle that logic outside of this code construct.

        By extension:

        #! perl -slw use strict; =comment N1234Z becomes N12350 N12359 becomes N1235A N9999Z becomes NA0000 =cut my $id = "F00123Z"; for ( 1 .. 80 ) { print $id; last if substr( $id, -5 ) eq '9999Z'; if( substr( $id, -1 ) eq 'Z' ) { substr( $id, -1 ) = '0'; substr( $id, 1, -1 )++; } elsif( substr( $id, -1 ) eq '9' ) { substr( $id, -1 ) = 'A'; } else { substr( $id, -1 ) ++; } }

        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.