2

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!!

  • Why don't you add checks to ensure that the same names don't match up? This no longer becomes random, but it seems like what you're looking for – A Person Dec 16 '13 at 02:44
  • How exactly would I go about doing this? I had an if function in a for loop stating that if the names were equal, then I would call the function again. This, however, didn't include all of the names and it didn't seem like the best solution. – Alex Neises Dec 16 '13 at 02:55
  • Rather than shuffling you could find random name for each name. and removing found name and the current name from the searchable array each time – jonasnas Dec 16 '13 at 03:17

2 Answers2

5

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.

Tony
  • 7,345
  • 3
  • 26
  • 34
0

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>
Pedro Moreira
  • 965
  • 5
  • 8