fork(7) download
  1. <?php
  2.  
  3. // your code goes here
  4. function randomFactory(array $data): Closure {
  5. $values = [];
  6. $rand = 0;
  7. foreach ($data as $value => $chance) {
  8. $values[] = [
  9. 'rand' => $rand += $chance,
  10. 'value' => $value,
  11. ];
  12. }
  13.  
  14. return function () use ($values) {
  15. $rand = random_int(0, PHP_INT_MAX) / PHP_INT_MAX;
  16. foreach ($values as $value) {
  17. if ($rand < $value['rand']) {
  18. return $value['value'];
  19. }
  20. }
  21.  
  22. throw new LogicException('smth get wrong');
  23. };
  24. }
  25.  
  26. $data = [
  27. 1 => 0.1,
  28. 2 => 0.25,
  29. 3 => 0.25,
  30. 4 => 0.4,
  31. ];
  32. $random = randomFactory($data);
  33.  
  34. $result = array_combine(array_keys($data), array_fill(0, count($data), 0));
  35. $attempts = 10000;
  36. for ($i = 0; $i < $attempts; ++$i) {
  37. $rand = $random();
  38. ++$result[$rand];
  39. }
  40.  
  41. echo "value\tcount\texpected\treal\tdiff", PHP_EOL, PHP_EOL;
  42. foreach ($result as $value => $count) {
  43. $real = $count / $attempts;
  44. $diff = abs($real - $data[$value]);
  45. printf("%d\t%5d\t%8.2f\t%.2f\t%.2f" . PHP_EOL, $value, $count, $data[$value], $real, $diff);
  46. }
Success #stdin #stdout 0.06s 23596KB
stdin
Standard input is empty
stdout
value	count	expected	real	diff

1	  999	    0.10	0.10	0.00
2	 2474	    0.25	0.25	0.00
3	 2569	    0.25	0.26	0.01
4	 3958	    0.40	0.40	0.00