简体   繁体   中英

Fragmenting the sequence to a maximum randomness (arrays, any language)

I had an interesting discussion with my good developer friends. I wanted to create a random sequence of given array values but with maximum fragmentation, without any detectable patterns. This so called maximum randomness would be practically always identical for any unique sequence.

Example input array:

array(1, 2, 3, 4, 5);

Example result of a standard rand() function:

array(2, 3, 1, 5, 4);

What I don't like in the output above are the sequence values like "2, 3" and "5, 4", It's not fragmented enough.

Expecting result would/could be:

array(3, 5, 1, 4, 2);

So my question; is there any known formula to calculate the maximum randomness or for better choice of words, maximum fragmentation?

So what are you talking about, not randomization, it is sorting. The result of randomization should not depend on order of the initial data.

By fragmentation in this case it is necessary to understand the differences between the array before sorting and after. But it must be evaluated differently depending on the task. For example, one can evaluate the difference between the positions of the elements or it's order.

Sorting example.

    <?
// it must be uksort() function with sequence formula, but for me easier do like this
    $array = array(1, 2, 3, 4, 5);
    uk_sort($array);
    function uk_sort(&$array) {
        for($i=0;$i<count($array);$i++) {
            if($i%2==0) {
                $even[] = $array[$i];
            } else {
                $odd[] = $array[$i];
            }
        }
        $even[] = array_shift($even);
        rsort($odd);
        $array = array_merge($even, $odd);
    }
    print_r($array);
    ?>
Array
(
    [0] => 3
    [1] => 5
    [2] => 1
    [3] => 4
    [4] => 2
)

You could split the list into two (or more) collections, shuffle those THEN mix them in order?

array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

array(1, 2, 3, 4, 5);
array(6, 7, 8, 9, 10);

array(2, 3, 1, 5, 4);
array(8, 7, 10, 9, 6);

array(2, 8, 3, 7, 1, 10, 5, 9, 4, 6)

This would give you a fairly high fragmentation but not the maximum. I suspect to get the maximum would require a LOT more work.

I think this sounds like a traveling salesman type problem, with the "distance" being the difference between two chosen entries, except your goal would be to maximize the total distance rather than minimize it.

I don't actually know a ton about the topic, but here's what I think I know:

There are algorithms for the traveling salesman problem, but they can be quite slow in the limit (they're NP-hard ). On the other hand, there are good approximations, and simple cases may be solvable, though it will still be a non-trivial algorithm.

Depending on how important it is to have maximum fragmentation, you could also try a naive method: given an element, choose the next element so that it's quite distant from the given element. Then choose a next element, and so on. The problem with this is that your early choices can back you into a corner. So this won't work if fragmentation is quite important to you.

[2,5,1,3,4] // the first three choices force us to not fragment the last two

Assuming the fragmentation is defined as the sum of the absolute differences of successive values, the maximum fragmentation sequence is not unique -- the reverse sequence will always have the exact same fragmentation and there're many more options, eg all the following orderings will have a fragmentation of 11, which is maximal for this array: (3,1,5,2,4), (3,2,5,1,4), (2,5,1,4,3), (2,4,1,5,3), (4,1,5,2,3), (4,2,5,1,3), (3,5,1,4,2), (3,4,1,5,2). There're yet more symmetries if one incorporates the difference between the last and the first element, too.

If one seeks to identify a particular maximum fragmentation sequence, eg the one "without a noticeable pattern", the latter notion has to be formalized and a search performed, which, I suspect, would be costly from the computational point of view, unless the objective can be formalized so as to permit efficient decoding. I suspect that for all practical purposes a good heuristic would suffice, eg inserting elements into an array one by one (greedy fashion) so as to maximize the gain in fragmentation on each step.

If the elements of the array are not numbers but some entities with a defined distance for each pair, however, the problem does become equivalent to the traveling salesman problem, as user802500 pointed out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM