The only catch is when you have to carry the '1'. You can't go z -> 0z, but z -> 1z makes sense. I prefer object-oriented, test-first solns. Here is what I got:
<?php
class NewMathCounter
{
/** This is an array, the values you'll use to count with */
var $_base;
var $_value;
function NewMathCounter( $base, $value = null )
{
$this -> _base = $base;
$this -> _value = array();
if( $value == null )
{
$this -> _value[ 0 ] = $this -> _base[ 0 ];
}
else
{
$this -> _value = $this -> _parse( $value );
}
}
function _parse( $string )
{
$len = strlen( $string );
$retVal = array();
$i = $len;
while( $i > 0 )
{
$retVal[] = substr( $string, $i - 1, 1 );
$i -= 1;
}
return $retVal;
}
function increment( )
{
//look at rightmost char, _value[ 0 ]
$col = 0;
$this -> _value[ $col ] = $this -> _incrementColumn( $this -> _value[ $col ] );
//if we get back a zero, then we need to carry the one!!!
while( $this -> _value[ $col ] == "0" )
{
$col += 1;
if( !isset( $this -> _value[ $col ] ) )
{
$this -> _value[ $col ] = $this -> _base[ 1 ];
}
else
{
$this -> _value[ $col ] = $this -> _incrementColumn( $this -> _value[ $col ] );
}
}
}
function _incrementColumn( $currentValue )
{
$index = array_search( $currentValue, $this -> _base );
if( $index < sizeof( $this -> _base ) - 1 )
{
return $this -> _base[ $index + 1 ];
}
return 0;
}
function getBase()
{
return sizeof( $this -> _base );
}
function toString()
{
$string = "";
for( $i = sizeof( $this -> _value ) - 1; $i >= 0; $i -= 1 )
{
$string .= $this -> _value[ $i ];
}
return $string;
}
}
?>
I think if you look at my simpletest unit test you'll understand how to use this...
<?php
error_reporting( E_ALL );
if (!defined('SIMPLE_TEST'))
{
define('SIMPLE_TEST', '/usr/local/simpletest/');
}
require_once(SIMPLE_TEST . 'unit_tester.php');
require_once(SIMPLE_TEST . 'reporter.php');
require_once '../repo/init.php';
require_once 'NewMathCounter.php';
class NewMathCounter_Test extends UnitTestCase
{
var $arr;
function NewMathCounter_Test()
{
$this->UnitTestCase();
$this -> arr = array( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z' );
}
function test_get_base()
{
$counter =& new NewMathCounter( $this -> arr );
$this -> assertEqual( 36, $counter -> getBase() );
}
function test_get_first()
{
$counter =& new NewMathCounter( $this -> arr );
$this -> assertEqual( "0", $counter -> toString() );
}
function test_increment()
{
$counter =& new NewMathCounter( $this -> arr );
$counter -> increment();
$this -> assertEqual( "1", $counter -> toString() );
}
function test_initial_value()
{
$counter =& new NewMathCounter( $this -> arr, "1z" );
$this -> assertEqual( "1z", $counter -> toString(), "got back " . $counter -> toString() );
$counter =& new NewMathCounter( $this -> arr, "4zff" );
$this -> assertEqual( "4zff", $counter -> toString(), "returned " . $counter -> toString() );
$counter =& new NewMathCounter( $this -> arr, "9" );
$counter -> increment();
$this -> assertEqual( "a", $counter -> toString(), "returned " . $counter -> toString() );
}
function test_roll()
{
$counter =& new NewMathCounter( $this -> arr, "z" );
$this -> assertEqual( "z", $counter -> toString() );
$counter -> increment();
$this -> assertEqual( "10", $counter -> toString(), "returned: " . $counter -> toString() );
//lets increment it...
$counter -> increment();
$this -> assertEqual( "11", $counter -> toString(), "returned: " . $counter -> toString() );
}
function test_roll_again()
{
$counter =& new NewMathCounter( $this -> arr, "zz" );
$counter -> increment();
$this -> assertEqual( "100", $counter -> toString(), "returned: " . $counter -> toString() );
//add one
$counter -> increment();
$this -> assertEqual( "101", $counter -> toString(), "returned: " . $counter -> toString() );
}
function test_printing()
{
$counter =& new NewMathCounter( $this -> arr );
for( $i = 1; $i < 1000; $i += 1 )
{
$counter -> increment();
echo "<br />" . $counter -> toString();
}
}
}
$test = &new NewMathCounter_Test();
$test -> run( new HtmlReporter() );
?>
🆒