Need an Algorithm for to Shuffle Elements of 5 Arrays, Each with the Same 5 Elements, Such That No Two Arrays Have the Same Element at the Same Index

Ruby. Shuffle the array so that there are no adjacent elements with the same value

The simple and maybe the less effective way could be the brute force.

So on a simplified version of the array, one can do:

ary = %w(a a c c b a s)

loop do
break if ary.shuffle!.slice_when { |a, b| a == b }.to_a.size == 1
end

Some check should be added to assure that a solution exists, to avoid infinite loop.


Other (better?) way is to shuffle then find the permutation (no infinite loop) which satisfy the condition:
ary.shuffle!    
ary.permutation.find { |a| a.slice_when { |a, b| a == b }.to_a.size == 1 }

If a solution does not exist, it returns nil.


Run the the benchmark:
def looping
ary = %w(a a c c b a s)
loop do
break if ary.shuffle!.slice_when { |a, b| a == b }.to_a.size == 1
end
ary
end

def shuffle_permute
ary = %w(a a c c b a s)
ary.shuffle!
ary.permutation.lazy.find { |a| a.slice_when { |a, b| a == b }.to_a.size == 1 }
end

require 'benchmark'

n = 500
Benchmark.bm do |x|
x.report { looping }
x.report { shuffle_permute }
end

Is there any difference between the following algorithms for shuffling arrays?

Yes, they are in fact different.

The first algorithm is a variant of the classic Knuth Shuffle.
For this algorithm, we can prove (e.g., by induction) that, if our random number generator (Math.random()) was an ideal one, it would generate every one of the n! (n factorial) possible permutations with equal probability.


The second algorithm does not have this property.
For example, when n = 3, there are 33 = 27 possible outcomes, and that does not divide evenly by 3! = 6, the number of possible permutations.
Indeed, here are the probabilities of outcomes (programs generating statistics: 1 2):

[0, 1, 2] 4/27
[0, 2, 1] 5/27
[1, 0, 2] 5/27
[1, 2, 0] 5/27
[2, 0, 1] 4/27
[2, 1, 0] 4/27

For n = 4, the results are even more uneven, for example (programs generating statistics: 3 4):

[1, 0, 3, 2] has probability 15/256
[3, 0, 1, 2] has probability 8/256

As you can imagine, this is an undesired property if your permutation is supposed to be uniformly random.


Lastly, the fact that we usually use a pseudorandom number generator instead of a true random source does not invalidate any of the above.
The defects of our random number generator, if any, are obviously unable to repair the damage at the later step - if we choose a non-uniform algorithm, that is.

Shuffle an Array coding challenge. trouble understanding one part

Yes, the Math.floor(Math.random() * n) expression can evaluate to the same number multiple times, but that's OK, because the random number is being used in swap, which switches the number at index i with the number at the chosen random index.

If the random index was taken from the original array and added to the array to be returned, eg

const randIndex = Math.floor(Math.random() * n);
arrToBeReturned.push(arr[randIndex]);

you'd be right, but that's not what the algorithm is doing. Imagine randomly sorting an array of [1, 2, 3]:

First iteration of loop: i is 0, random index chosen is 2. Swap indicies 0 and 2:

[3, 2, 1]

Second iteration: i is 1, random index chosen is 2. Swap indicies 1 and 2:

[3, 1, 2]

Third iteration: i is 2, random index chosen is 2. Swap indicies 2 and 2:

[3, 1, 2]

With this code, every index is randomly swapped with another index at least one time, ensuring that by the end, the array is randomized without bias (assuming Math.random is trustworthy).

How to shuffle an array so that all elements change their place

For each element e
If there is an element to the left of e
Select a random element r to the left of e
swap r and e

This guarantees that each value isn't in the position that it started, but doesn't guarantee that each value changes if there's duplicates.

BeeOnRope notes that though simple, this is flawed. Given the list [0,1,2,3], this algorithm cannot produce the output [1,0,3,2].

Shuffle arrays of strings in JavaScript with repeated elements that are at least two elements apart

The easiest would probably be doing it in two steps.

  1. Shuffle array1 with a standard fisher-yates algorithm.
  2. Insert the elements at random positions satisfying the conditions.

Ie something like the following (I assume, you can implement fisher yates, thus I didn't include it here and just made an (unshuffled) copy of the array)

let array1 = [1,2,3,4,5,6,7]
let array2 = [8,9]

let rand = (n) => Math.floor(Math.random()*n);

//let shuffled = fisheryates(array1);
let shuffled = array1.slice(); //just make a copy of the array

while (array2.length) {
let e = array2.splice(rand(array2.length), 1)[0];
let i1 = shuffled.length == 2
? 0
: rand(shuffled.length + 1);
let i2 = 0;
do {
i2 = shuffled.length == 2
? 2
: rand(shuffled.length + 1);
}
while (Math.abs(i1 - i2) < 2)

if (i1 < i2) {
shuffled.splice(i2, 0, e);
shuffled.splice(i1, 0, e);
} else {
shuffled.splice(i1, 0, e);
shuffled.splice(i2, 0, e);
}
}

console.log(shuffled)

Shuffle element such that, no element should come at its original index

This works for me:

var SourceList = new List<string>()
{
"Obj_A", "Obj_B", "Obj_C", "Obj_D", "Obj_E", "Obj_F", "Obj_G",
};

var rnd = new Random();

var ResultList =
Enumerable
// create an exceedingly long sequence for retries
.Repeat(0, int.MaxValue)
// select and randomly order all of the indices of `SourceList`
.Select(_ => Enumerable.Range(0, SourceList.Count)
.OrderBy(x => rnd.Next())
.ToArray())
// Discard the indices if they have any matching positions
.Where(x => !x.Where((y, i) => y == i).Any())
// only take one successful set of indices
.Take(1)
// flatten the list of lists to a list
.SelectMany(x => x)
// select the elements from `SourceList` from their index positions
.Select(x => SourceList[x])
// convert to list
.ToList();

The use of .OrderBy(x => rnd.Next()) produces a uniform ordering (no bias) - I have confirmed this in the past.

How to randomize (shuffle) a JavaScript array?

The de-facto unbiased shuffle algorithm is the Fisher-Yates (aka Knuth) Shuffle.

You can see a great visualization here (and the original post linked to this)

function shuffle(array) {
let currentIndex = array.length, randomIndex;

// While there remain elements to shuffle.
while (currentIndex != 0) {

// Pick a remaining element.
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;

// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}

return array;
}

// Used like so
var arr = [2, 11, 37, 42];
shuffle(arr);
console.log(arr);


Related Topics



Leave a reply



Submit