Question

I have a javascript problem. I have a user enter a list of names, which I then place into an array. Long story short, I am programming a random way for people to figure out who they will buy Christmas gifts for. For instance, the original array consists of the following names:

Alex
Joel
Lindsay
Cori

I want to then randomize the names so that I get a random list, similar to the following:

Lindsay
Cori
Joel
Alex

I would then display the names from the first array and align them with the randomized name in the same location. For instance, in this example, Alex is associated with Lindsay, Joel is associated with Cori, Lindsay is associated with Joel, and Cori is associated with Alex. I am currently using the following randomize method:

function shuffle(array){
    var m = array.length, t, i;
    while(m){
        i = Math.floor(Math.random() * m--);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
};

The problem with this function is that the array does not randomize into a new location. For instance, with this method, I can have the following initial array:

Alex
Joel
Lindsay
Cori

And my array, with the above function to randomize it, will result in something like this:

Cori
Alex
Lindsay
Joel

This means that Alex is associated with Cori, Joel is associated with Alex, Lindsay is associated with Lindsay, and Cori is assocated with Joel. This is where the problem lies. If this is a program to see who buys a Christmas gift for whom, Lindsay can NOT buy a gift for Lindsay.

What would be an appropriate array randomizing function to fix this issue?

Thank you for the assistance!!

Was it helpful?

Solution

Try --m, not m--:

function shuffle(array){
    var m = array.length, t, i;
    while(m){
        i = Math.floor(Math.random() * --m);
        t = array[m];
        array[m] = array[i];
        array[i] = t;
    }
    return array;
};

Because if you use m-- you can possibly get i == m and swap array element with itself.

OTHER TIPS

First I built an array of indexes, then shuffled it and checked the final stuck.

I think this is what you want: (I added a check at the end, remember to remove it)

<script>
    var start = [ 'Alex', 'Joel', 'Lindsay', 'Cori' ]

    function shuffle(array) {
        // Support
        var support = [];
        for(var i = 0; i < array.length; i++) {
            support[i] = i;
        }

        // Support Build
        for(var i = 0; i < support.length; i++) {
            var random = Math.floor(Math.random() * (support.length - i)) + i;

            if(i == (support.length - 2) && support[i + 1] == (i + 1)) {
                var ex = support[i];
                support[i] = support[i + 1];
                support[i + 1] = ex;
                break;
            }

            if(random == support[i]) {
                i--;
                continue;
            }

            var ex = support[i];
            support[i] = support[random];
            support[random] = ex;
        }

        // Result
        var result = [];
        for(var i = 0; i < support.length; i++) {
            result[i] = array[support[i]];
        }

        return result;
    };

    for(var i = 0; i < 1000; i++) {
        if(start == shuffle(start))
            alert('fail.');
    }
</script>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top