数组洗牌和撤消

array shuffle and undo

如下代码,

<?php
// sort array in a fixed order with given seed
function do_shuffle( $array, $seed ) {
    mt_srand( $seed );
    usort( $array, fn() => mt_rand( - 9, 9 ) );
    return $array;
}

// the reverse operation of do_shuffle
function undo_shuffle( $array, $seed ) {
    return $array; // to implement
}

$origin_array = str_split( 'olive tree' );

$seed = 20220502;

$shuffled_array = do_shuffle( $origin_array, $seed );
var_dump( $shuffled_array );

// undo shuffle
$origin_array = undo_shuffle( $shuffled_array, $seed );
var_dump( $origin_array );

数组shuffle及其逆向操作如何实现?

如何return $shuffled_array 到 $origin_array?

关键思想是重新创建一个进程,但不是随机排列数组值,而是随机排列数组索引。这为我们提供了混洗索引和原始索引之间的映射:

// the reverse operation of do_shuffle
function undo_shuffle( $array, $seed ) {
    mt_srand( $seed );

    $indices_map = range(0, count($array) - 1);

    // We do just the same shuffle operation but
    // shuffling array indices instead of values
    usort( $indices_map, function(){ 
      return mt_rand( - 9, 9 );
    } );

    // Restore original array using the map we've created
    $out = [];
    foreach( $indices_map as $shuffled_index => $original_index )
      $out[ $original_index ] = $array[ $shuffled_index ];

    // Sort our output by integer key
    ksort($out);

    return $out;
}