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:
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.
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: