根据种子改组数组以获得始终相同的结果? [英] Shuffling array based on seed to get always the same result?

查看:113
本文介绍了根据种子改组数组以获得始终相同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要根据种子编号对数组进行随机排序,以便在需要时可以进行相同的随机排序。

I need to shuffle an array based on a seed number so I can get the same shuffle if I need it.

例如:

1. print_r( shuffleIt( $array, 2 ) );
2. print_r( shuffleIt( $array, 6 ) );
3. print_r( shuffleIt( $array, 2 ) );




  1. 和3将显示相同的改组数组,但不同于2。

我发现该函数在谷歌搜索:

I found this function googling:

function entropy( $array, $sort_seed ) {
    mt_srand( $sort_seed );
    $order = array_map( create_function( '$val', 'return mt_rand( );' ), range( 1, count( $array ) ) );
    array_multisort( $order, $array );
    return $array;
}

在我的PC上使用php-cli效果很好,我总是得到相同的结果我使用的每个不同sort_seed数组,但是当我将其上传到服务器时,即使使用相同的sort_seed,我每次也会得到不同的数组。

It works fine on my pc with php-cli, I always get the same array for each different sort_seed I use, but when I uploaded it to a server, I get different arrays every time even when I am using the same sort_seed.

btw,当我使用相同的sort_seed时,如何总是得到相同的改组数组?我需要保留键或对多维数组进行排序,以便可以在其中存储键。

btw. I need to preserve keys or sort a multidimensional array so I can store the key there.

推荐答案

如果在任何PC上都需要它,您需要一个随机数生成器,该生成器在计算机之间的工作原理相同。我从随机数生成Wikipedia页面中查找了一个可能适合您的伪随机数生成器

If you need it on any pc, you need a random number generator that works the same across computers. I looked up one pseudo-random-number generator that might be suitable for you from the Random Number Generation Wikipedia page and put it into a class so you can seed it.

我不知道您需要什么,但这可能满足您的需求。它独立于系统配置:

I don't know for what you need it, but this just might suit your needs. It's independent to system configuration:

function shuffleIt($array, $seed)
{
    $mwc = new mwc($seed);
    $order = array();
    $count = count($array);
    while($count--)
        $order[] = $mwc->random()
    ;

    array_multisort($order, $array);
    return $array;
}

/**
 * Multiply-with-carry RNG
 * 
 * method invented by George Marsaglia
 */
class mwc
{
    private static $def_m_w = 1712; /* must not be zero */
    private static $def_m_z = 23;   /* must not be zero */
    private $m_w, $m_z;
    public function __construct($seed = NULL)
    {
        $this->m_w = self::$def_m_w;
        $this->m_z = self::$def_m_z;
        if (NULL !== $seed)
            $this->seed($seed);
    }
    public function seed($seed)
    {
        $seed = (int) $seed;
        if (!$seed) throw new InvalidArgumentException('Must not be zero.');
        $this->m_z = $seed;
        $this->random();
    }
    public function random()
    {
        $this->m_z = 36969 * ($this->m_z & 65535) + ($this->m_z >> 16);
        $this->m_w = 18000 * ($this->m_w & 65535) + ($this->m_w >> 16);
        return ($this->m_z << 16) + $this->m_w;  /* 32-bit result */
    }
}

注意:在32/64位系统之间,此行为可能有所不同,尤其是PHP在Windows和Unix之间的整数和溢出方面有所不同。您可能希望将PHP中32位整数的有符号最小值偏移而不是现在的0,将实现切换到 gmp 或只是将大小减小一点。

Note: This might behave differently between 32/64 bit systems, especially as PHP differs here for integers and overflows between windows and unix. You might want offset at the signed minimum for 32 bit integers in PHP instead of 0 as it is now, to switch the implementation to gmp or just reduce the size by one bit.

用法示例32位据报道由ekke在荷兰工作。

Usage Example 32 bit reported to work by ekke from netherlands

$shuffle = new GeorgeShuffle();
$seed    = $shuffle->seed();
$a       = array('A', 'B', 'C', 'D', 'E', 'F', 'G');
$shuffle->reOrder($a);
var_dump($a);
$shuffle->seed($seed);
$shuffle->reOrder($a);
var_dump($a);

/**
 * Array shuffle class using
 * the multiply-with-carry method
 * invented by George Marsaglia
 */
class GeorgeShuffle
{

    private static $def_m_w = 1959; /* must not be zero */
    private static $def_m_z = 2006; /* must not be zero */
    private $m_w, $m_z;
    const maxint = 2147483647;

    public function __construct($seed = null)
    {
        $this->m_w = self::$def_m_w;
        $this->m_z = self::$def_m_z;
        if ($seed) $this->seed($seed);
    }

    public function reOrder(&$array, $seed = null)
    {
        if (!empty($seed)) $this->seed($seed);
        $a = array();
        for ($i = 0, $j = count($array); $i < $j; $i++) {
            $a[$i] = $this->random();
        }
        array_multisort($a, $array);
        //- to return a copy, remove the &
        return $array;
    }

    public function seed($seed = false)
    {
        if (is_string($seed)) $seed = hexdec($seed);
        if (empty($seed)) $seed = round(mt_rand(1, self::maxint));
        $this->m_z = $seed;
        $this->random();
        //- return the seed used in hex (8 chars) for reproducing
        return str_pad(dechex($seed), 8, '0', STR_PAD_LEFT);
    }

    public function random()
    {
        $this->m_z = 36969 * (($this->m_z And 65535) + ($this->m_z >> 16));
        $this->m_w = 18000 * (($this->m_w And 65535) + ($this->m_w >> 16));
        return ($this->m_z << 16) + $this->m_w; /* 32-bit signed result */
    }
}

这篇关于根据种子改组数组以获得始终相同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆