我想编写一个函数,每次从一个范围调用它时返回随机唯一对数,直到重置它为止。 像这样:
function randomUniquePairs($ranges, $reset = false){
if ($reset === false){
// some code for reseting
}
/*
some code for creating random unique pair numbers
*/
return $result;
}
randomUniquePairs(range(1,10), range(1,20));
/*
this function returns for example:
array(2,9)
*/
randomUniquePairs(range(1,10), range(1,20));
/*
this function returns for example:
array(5,19)
*/
randomUniquePairs(range(1,10), range(1,20));
/*
this function returns for example:
array(5,19)
*/
//this function returns random unique pairs until we pass reset paramer true
我尝试了两种方法:
1)其中一个是制作所有可能的对,然后随机选择它们,但效率非常低,因为如果范围太宽,则会消耗大量内存。 代码:
class a {
private $asqar;
function __construct() ($range) {
// cycle for ranges
foreach ($range[0] as $v1) {
foreach ($range[1] as $v2) {
$asqar[] = array(
$v1,
$v2,
);
}
}
}
function randomUniquePairs($reset = false){
if ($reset === true){
$this->asgar = array();
}
$rndKey = array_rand($this->asgar);
$result = $this->asqar[$rndkey];
unset($this->asqar[$rndkey]);
return $result;
}
}
$c = new a(range(1,10), range(1,20));
$c->randomUniquePairs();
2)第二个是写一个从这些范围产生一对的函数,然后将它存储在一个变量中,每次该函数在产生一对后调用,它会检查这对在递归调用函数之前是否产生,它会一直持续到它产生一对独特的。 这段代码:
class a{
private $__uniqueVariables = array();
public function randomUniquePairs($range, $reset = false) {
if ($reset === true){
$this->__uniqueVariables = array();
}
// cycle for each value
foreach ($range as $value) {
// shuffle
shuffle($value);
// selected id
$selectedId[] = $value[0];
}
// check for selected variable
if (in_array($rndUnqNum, $this->__uniqueVariables)) {
// return for try again
return $this->uniqueVariable($range);
}
// added to current unique variables
$this->__uniqueVariables[] = $rndUnqNum;
// return
return $rndUnqNum;
}
}
但这有一个问题,有时会抛出Fatal error: Maximum function nesting level of '100' reached
。
我想要更好的算法。
答案 0 :(得分:1)
即使在大范围内,这似乎也很好:
rand() function是获取指定范围内的随机整数的好方法,无需构造或操作值数组,如上例所示。
更新我添加了一个停止案例(当历史记录等于或大于最大可能的唯一对时,它返回一个空数组)。随意更改该代码以自动重置范围。
<?php
class c {
function c($min_X,$max_X,$min_Y,$max_Y) {
$this->setRange($min_X,$max_X,$min_Y,$max_Y);
}
function getRandUniquePair($reset = false) {
if ($reset) {
$this->__history = array();
}
if (count($this->__history) >= $this->__max_pairs) {
return array();
}
$candidate = array(rand($this->__range[0],$this->__range[1]),rand($this->__range[2],$this->__range[3]));
if (in_array($candidate,$this->__history)) {
return $this->getRandUniquePair();
}
$this->__history[] = $candidate;
return $candidate;
}
function setRange($min_X,$max_X,$min_Y,$max_Y) {
$this->__range = array($min_X,$max_X,$min_Y,$max_Y);
$this->__max_pairs = ($max_X - $min_X) * ($max_Y - $min_Y);
$this->__history = array();
}
}
// test
$c = new c(0,10,0,20);
$i = 0;
$pairs = array();
while ($i < 100) {
$i++;
$pair = $c->getRandUniquePair();
if (in_array($pair,$pairs)) {
die('Duplicate pairs!');
}
echo $pair[0].', '.$pair[1]."\n";
$pairs[] = $pair;
}
$c->setRange(0,100000000000,0,100000000000);
echo "I perform well even at large ranges!\n";
$i = 0;
while ($i < 1000) {
$i++;
$pair = $c->getRandUniquePair();
echo $pair[0].', '.$pair[1]."\n";
}
?>