Math & php: FAST array type [1..N] in a special way

$array = array(1, 2, 3, 4, 5, ..., N); 

There is also a number D = 10% . What is the fastest way to sort an array so that:

 $sorted_array = {a[i]} 

contains exactly elements from $array in mixed order, but also:

 abs(a[i + 1] - a[i]) >= N * 10% 

for any [i] and look as random as possible.

For instance,

 // assume D = 25% $array = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // so the difference between any neighbors is >= 4 = 10 * 25%. $sorted_array = array(4, 8, 3, 7, 1, 5, 9, 2, 6, 10); 

Of course, if D large, it is not possible to sort the array I want. I don’t need a 100% quality result, but I want the numbers to look “randomized”, and most of them differ by at least 10%.

I have a strange task, but it has a practical area to use. I want to extract randomized strings from an image, and they should be as different as possible. Of course, adjacent lines in digital images (photographs, etc.) look very similar.

Did I explain this correctly?

+4
source share
1 answer

I know that it is not a good idea to just provide the code, but I was intrigued by this question. Here's how I do it:

 $d = 0.3; $random = array(); // Populate the original array for ($n=1; $n <= 10; $n++) { $arr[] = $n; } $count = count($arr); // Loop through array foreach (array_keys($arr) as $key) { if (!isset($prev_key)) { $prev_key = array_rand($arr); } $possibles = array(); // This stores the possible values echo "Trying: $prev_key"; echo ":\n"; // Loop through the array again and populate $possibles with all possible // values based on the previous values foreach (array_keys($arr) as $n) { if ($arr[$n] < $prev_key - $count * $d || $arr[$n] > $prev_key + $count * $d) { $possibles[] = $n; echo $arr[$n]." is valid\n"; } else { echo $arr[$n]; echo " outside range\n"; } } // If there is nothing outside that range, just return the remaining values if (count($possibles) == 0) { $possibles = array_keys($arr); echo "Nothing within range so just returning whole array\n"; } echo "\n"; // Choose random value from the possible values array $rand_key = $possibles[array_rand($possibles)]; $random[] = $arr[$rand_key]; $prev_key = $arr[$rand_key]; // Unset this value from the original array since we can only use the // values once unset($arr[$rand_key]); } print_r($random); 

This will create the following form:

 Trying: 8: 1 is valid 2 is valid 3 is valid 4 is valid 5 outside range 6 outside range 7 outside range 8 outside range 9 outside range 10 outside range Trying: 2: 1 outside range 3 outside range 4 outside range 5 outside range 6 is valid 7 is valid 8 is valid 9 is valid 10 is valid Trying: 9: 1 is valid 3 is valid 4 is valid 5 is valid 6 outside range 7 outside range 8 outside range 10 outside range Trying: 5: 1 is valid 3 outside range 4 outside range 6 outside range 7 outside range 8 outside range 10 is valid Trying: 10: 1 is valid 3 is valid 4 is valid 6 is valid 7 outside range 8 outside range Trying: 4: 1 outside range 3 outside range 6 outside range 7 outside range 8 is valid Trying: 8: 1 is valid 3 is valid 6 outside range 7 outside range Trying: 3: 1 outside range 6 outside range 7 is valid Trying: 7: 1 is valid 6 outside range Trying: 1: 6 is valid Array ( [0] => 2 [1] => 9 [2] => 5 [3] => 10 [4] => 4 [5] => 8 [6] => 3 [7] => 7 [8] => 1 [9] => 6 ) 

The only drawback is that since it randomly receives strings, there is a possibility that the values ​​near the end may not be outside the given range. According to my tests, this happens by about 4%, using the above values ​​of $d = 0.25 and 1000. One way to get around this is to simply paste these values ​​into random places, and not add them as I did.

Also note: this method is not so efficient. It should go through the count($arr) ^ 2 array count($arr) ^ 2 times. So for 1000 values ​​you are looking at 1,000,000 iterations. Fortunately, the array is getting smaller.

+2
source

Source: https://habr.com/ru/post/1495389/


All Articles