views:

291

answers:

2

I'm wondering if this is a sufficient algorithm for finding the best value with a weighted system. Is there anything I could add to make it better?

Edit:

in this example I would like the probability of $object->get() returning test4 to be 4 times greater than the probability of it returning test1 (thanks acrosman)

Thanks

class weightCalculator { 
    var $data = array();
    var $universe = 0; 

    function add( $data, $probability ){ 
        $this->data[ $x = sizeof( $this->data ) ] = new stdClass; 
        $this->data[ $x ]->value = $data; 
        $this->universe += $this->data[ $x ]->probability = abs( $probability ); 
    } 

    function get(){ 
        if( !$this->universe ){
            return null; 
        }
        $x = round( mt_rand( 0, $this->universe ) ); 
        $max = 0;
        $i = 0; 

        while( $x > $max ){
            $max += $this->data[ $i++ ]->probability;
        }
        $val=-1;
        if($this->universe==1){
            $val = $this->data[$i]->value;   
          } else {
            $val = $this->data[$i-1]->value;       
        }
        return $val;
    } 
}

$object = new weightCalculator; 
$object->add( 'test1', 10 );
$object->add( 'test2', 20 ); 
$object->add( 'test3', 30 ); 
$object->add( 'test4', 40 );
A: 

Seems fair enough, depends on the use. If you need better performance for the get() method, you could build your range values in the add() method and use dichotomy.

streetpc
A: 

To elaborate on streetpc's answer; alongside your data array, use add() to maintain a same-sized keys array where you store the upper bound on your range; for your example, that array would look like {10, 30, 60, 100}. (Or, use one array containing objects or structs that contain both the data and the key.) Then, your get() method is simply searching a sorted list for the first element greater than $x; a binary search could do that in O(ln N), compared to O(N) for your method. You'll chew up a little extra memory -- but for most applications, it looks like a good tradeoff.

Richard Dunlap