Reputation: 157
I have a int called v_cnt which im using a maximum value for a voting system, them im using mt_rand to generate a random number of 'votes' (used for gaming purposes not a rigged system)
// vote 1
$vote_limit = $v_cnt;
$vote_1 = mt_rand(0, $vote_limit);
// vote 2
$vote_limit = $v_cnt - $vote_1; if($vote_limit < 0){ $vote_limit = 0;}
$vote_2 = mt_rand(0, $vote_limit);
// vote 3
$vote_limit = $v_cnt - ($vote_1 + $vote_2); if($vote_limit < 0){ $vote_limit = 0;}
$vote_3 = mt_rand(0, $vote_limit);
This gives me vote_1, vote_2 and vote_3 which is ideal. But, since mt_rand is a random value up to the limit, im not getting quite the result i need as i need it to calculate like this;
(vote_1 + vote_2 + vote_3) = $v_cnt
So essentially i need to split an int into 3 random values which must add up to equal the starting number. I hope this makes sense.
Thank you.
Upvotes: 0
Views: 81
Reputation: 23958
You can't have all three random. It's impossible.
The first two, sure. But the last one can only be one number and that is what is remaining.
// vote 1
$vote_limit = $v_cnt;
$vote_1 = mt_rand(0, $vote_limit);
// vote 2
$vote_limit = $v_cnt - $vote_1;
$vote_2 = mt_rand(0, $vote_limit);
// vote 3
$vote_3 = $v_cnt - ($vote_1 + $vote_2);
Also I'm not sure what you expect this line to do: if($vote_limit < 0){ $vote_limit = 0;}
.
$vote_limit can't be negative since you have a limit of the random number.
$v_cnt = 100;
$n_votes = 3;
$numbers = range(0,$v_cnt); // create array of 0->100
shuffle($numbers); // shuffle the array
$votes = array_fill(0, $n_votes-1, 1); // create an array that will NOT exit loop below.
// Array_fill returns [1,1,1] which does not match the requirements so the loop starts
//Loop until all values in votes are unique and none is negative
while(count(array_unique($votes)) != $n_votes || $votes[$n_votes-1]<1){
// Take two consecutive numbers of random place in the array
$votes = array_slice($numbers, mt_rand(0, $v_cnt-$n_votes+1),$n_votes-1);
// Count what the last item should be
$votes[] = $v_cnt - array_sum($votes);
}
echo array_sum($votes) . "\n";
Var_dump($votes);
Just as a fun thing to look at, if I include a $i in the code we can see how many tries in the loop was needed to create the unique array. https://3v4l.org/mPae5
Keep in mind this code is very sensitive to max limit opposed to number of votes.
If you have a relatively low $v_cnt and a high $n_votes it may never find the numbers needed.
Just try and set $n_votes to 5 in the latest link and you can see that $i number can be 100+ (meaning more than 100 loops was needed to get a correct set of numbers).
Upvotes: 1
Reputation: 1523
here is how I would handle this...
$vote_limit = $v_cnt;
$numbers_required = 3;
for($i=1;$i<=$numbers_required;$i++)
{
if($i != $numbers_required)
{
$votes[$i] = mt_rand(0, $vote_limit);
$vote_limit -= $votes[$i];
} else {
$votes[$numbers_required] = $v_cnt - array_sum($votes);
}
}
echo $votes[1]; // First
echo $votes[2]; // Second
echo $votes[3]; // Third
Upvotes: 0