Search code examples
phpstringsequenceincrementalphanumeric

Generating Alphanumeric Codes in Sequence from AAA000 to ZZZ999


I needed to create a sequence of unique alphanumeric codes in PHP, starting from 'AAA000' and incrementing up to 'ZZZ999'. The codes should follow this pattern:

  • From 'AAA000' to 'AAA999', then 'AAB000' to 'AAB999', and so on.
  • After 'AAZ999', it should continue with 'ABA000' instead of 'ABZ000'.
  • The final code should be 'ZZZ999'.

This pattern should give a total of 17,576,000 unique codes. I was initially unsure of how to handle the incrementation, especially when rolling over from 'AAZ999' to 'ABA000'. However, I've developed a solution in PHP that seems to work.

My Current Solution:

for($letter_code = 'aaa'; $letter_code < 'zzz'; $letter_code++){
    if($letter_code != 'zzy'){
        for($number_code = 0; $number_code <= 999; $number_code++){
            $code_str_number = str_pad($number_code, 3, "0", STR_PAD_LEFT);
            $total_records_processed_count++;
            print (strtoupper($letter_code).$code_str_number."\n");
        }
    } else {
        // Handle 'ZZZ' after 'ZZY'
        for($number_code = 0; $number_code <= 999; $number_code++){
            $code_str_number = str_pad($number_code, 3, "0", STR_PAD_LEFT);
            $total_records_processed_count++;
            print (strtoupper($letter_code).$code_str_number."\n");
        }
        for($number_code = 0; $number_code <= 999; $number_code++){
            $code_str_number = str_pad($number_code, 3, "0", STR_PAD_LEFT);
            $total_records_processed_count++;
            print ("ZZZ".$code_str_number."\n");
        }
    }
}

Explanation:
I used a nested loop, the outer for the alphabetic part and the inner for the numeric part. To handle the numeric part, I used str_pad to ensure the number always has three digits. The special case for when $letter_code reaches 'zzy' is handled to include 'ZZZ'.

Question:
While this code works, I'm interested in knowing if there's a more efficient or elegant way to achieve the same result, particularly in handling the special case when the code rolls over from 'ZZY999' to 'ZZZ000'.

If anyone has any idea how I can better this question please leave me a comment and I will make amendments.


Solution

  • Since PHP8.3 released str_increment() (and str_decrement()), all potential headaches with this task are eliminated.

    Code: (Demo)

    $tests = [
        'AAA000',
        'AAA999',
        'AAZ999',
        'AZZ999',
        'ZZY999',
        'ZZZ999',
    ];
    
    foreach ($tests as $t) {
        echo "\n$t => " . str_increment($t);
    }
    

    Output:

    AAA000 => AAA001
    AAA999 => AAB000
    AAZ999 => ABA000
    AZZ999 => BAA000
    ZZY999 => ZZZ000
    ZZZ999 => AAAA000 <- throw a business logic exception if you like
    

    To print a large amount of these alphanumeric values, it will probably be advisable to use a generator. For smaller volumes of data, simple loops will suffice.

    Code: (Demo)

    function incGen(string $alnum = 'AAA000', string $stopBefore = 'AAAA000')
    {
        if (!preg_match('/^[A-Z]{3}\d{3}$/', $alnum)) {
            throw new Exception('Invalid alnum value');
        }
        if ($stopBefore !== 'AAAA000' && !preg_match('/^[A-Z]{3}\d{3}$/', $stopBefore)) {
            throw new Exception('Invalid stopBefore value');
        }
        if ($alnum > $stopBefore) {
            throw new Exception('stopBefore cannot be reached by incrementation');
        }
        while ($alnum !== $stopBefore) {
            yield $alnum;
            $alnum = str_increment($alnum);
        }
    }
    
    foreach (incGen('AAA980', 'AAC123') as $value) {
        echo "$value\n";
    }
    

    Related reading: