Array calculation

I want to take each value of an array $a and subtract that value from another number $int

so if $a=array(1,4,1331,76);
and $int=200

I would get back an array $a of values (199,196,-1131,124)

php doesn’t like anything I have tried, am I missing something?

$a=$int-$a;

Someone may be able to suggest a better way of doing what I want anyway.

I have a list of items with an associated count.

eg.
$cars=array($blue => 12,$red=37,$green=66);

I want to randomly select a new colour, with it more likely to be a lesser used colour. in this case blue being most likely.

I was going to loop through and then take the value of the (total - the colour count), then select a number from between 1 and that total. (n-1)*total where n is the number of items in the array. Hence needing the above…


$int=200;
$a=array(1,4,1331,76);
array_walk($a, create_function('&$v,$idx,$i', '$v-=$i;'), $int);

(not tested)

If you want to select the item from array which has the smallest value, then it’s not random. Random means picking something totally by chance, regardless of value or any condition.

If you want to select by least value, then just use the min()

I want to weight the randomness by those values.

if I am aiming at a board which is 60% black and 40% green, but I throw my arrow randomly it will land on black 60% of the time right?

I need the opposite… kind of…

I see. I remember such function exists in C++ RandomChance(double probability)
You pass it probability like 0.25 and it will return true with 25% probability.
It’s ashame php does not have this function. I really don’t know how to do this in php but I’m sure there is some clever hack that can produce similar result, probably by playing with mt_rand($min, $max)

Well, it’s not hard to functionalize both.
Weight = Total - Cur (Array_sum - value)
This then results in a weighted chance towards the lower-counted-values.

EG:
blue: 12
black: 20
red: 36

Total = 68
blue chance = 68-12 = 56
black chance = 68-20 = 48
red chance = 68-36 = 22

rand(totalchances), and use the weights to determine the value;
56+48+22 = 126
rand(126); lets say it’s… 72.
56+48 > 72, so it’s Black.

Off the top of my head (untested)…
This is set to return the numerical index of the element chosen - if you want the key instead, change $holder in the return line to array_shift(array_slice(array_keys($inarray),$holder,1)));


function iweightrand($inarray) {
 $total = array_sum($inarray);
 array_walk($inarray,create_function('&$a,$key,$tot','$a=$tot-$a'),$total);
 $total = array_sum($inarray);
 $value = rand($total);
 $holder = 0;
 $sum = 0;
 while(true) {
   $sum += array_shift(array_slice($inarray,$holder,1));
   if($sum > $value) { return $holder; }
   $holder++;
 }
 //We should never ever get here.
}

Aw, that’s much better than mine.


<?php
$items = array(
  'red'   => 10,
  'green' => 3,
  'blue'  => 1
);

function get_reverse_weighted(&$items){
  $weighted = array();
  foreach(array_reverse($items, true) as $item => $qty){
    foreach(range(1, array_shift($items)) as $i){
      $weighted[] = $item;
    }
  }
  return $weighted[array_rand($weighted)];
}

print_r(
  get_reverse_weighted($items)
);
?>

Anthony - i’m leery of playing around with the array that way - reverse will screw the key association of a numeric array, and you’re playing with it by reference…and then you’re shifting elements off into the aether…

Oh I agree. Scary isn’t it. :stuck_out_tongue: