CharpoolCounter - or: How to count like spreadsheets do
Abstract
Pretty much everyone has seen it in one spreadsheet application or the other: While the rows are counted 1, 2, 3, ..., the columns are numbered from A to Z and then beginning again at AA to AZ, BA to BZ and so on.
It is common knowledge that in PHP you can archieve this behaviour by setting a variable to "a" and then incrementing it step by step - no big deal. But what if you don't want to use the whole alphabet ... or no connected set of characters at all? This is where this little class comes in.
The code
class CharpoolCounter {
private $pool, $poolsize, $pos;
public function __construct($pool) {
if (is_array($pool))
$this->poolsize = sizeof($this->pool = $pool);
else
$this->poolsize = strlen($this->pool = (string)$pool);
$this->pos = array();
}
public function get() {
$s='';
$n=sizeof($this->pos);
while($n--)
$s.=$this->pool[$this->pos[$n]];
return $s;
}
public function iterate() {
for($i=0; $i<sizeof($this->pos); $i++) {
if (++$this->pos[$i] == $this->poolsize)
$this->pos[$i]=0;
else
break;
}
if ($i==sizeof($this->pos))
$this->pos[] = 0;
return $this->get();
}
};
Usage example
Example code
$it = new CharpoolCounter('abc');
for($i=0; $i<13; $i++)
echo $it->iterate(), "\n";
Output
a
b
c
aa
ab
ac
ba
bb
bc
ca
cb
cc
aaa
How does it work?
This is actually just a counter counting up using a sizeof($pool)-ary base. Thus in our example it counts ternary ("a", "b", "c" = three items).
What is non-standard is, that the counter, when reaching the largest possible number that can be represented with the current number of digits, it doesn't continue but instead it zero fills to one more digit and resets to zero.
That is: Instead of counting
..., 8, 9, 10, 11, ..., 98, 99, 100, ...
it counts
..., 8, 9, 00, 01, ..., 98, 99, 000, ...
If you look closely, you will spot that CharpoolCounter::$pos is an array containing the single digits (though for easier implementation it contains them in reverse order). Also because each digit is its own array element, you are not limited to ten or less digits, but can pass any number of them.
