Skip to content Skip to sidebar Skip to footer

Fischer Yates Shuffle In Coffee-script

Assuming that Math.random() produces evenly distributed random numbers between 0 and 1, is this a correct implementation of the Fischer Yates shuffle? I am looking for a very rando

Solution 1:

A couple things:

  • Rather than Math.round(), try Math.floor(); in your implementation Math.round() gives the first element (at index 0) and the last element less of a chance than all the other elements (.5/len vs. 1/len). Note that on the first iteration, you input arr.length - 1 for arr.length elements.
  • If you're going to have a required variable, you might as well make it optional, in that it defaults to the length of the array: shuffle = (arr, required=arr.length)
  • You return the entire array even though you only shuffled the last elements. Consider instead returning arr[arr.length - required ..]
  • What if required isn't in the range [0,arr.length]?

Putting it all together (and adding some flair):

    shuffle = (arr, required=arr.length) ->
      randInt = (n) -> Math.floor n * Math.random()
      required = arr.length if required > arr.length
      return arr[randInt(arr.length)] if required <= 1for i in [arr.length - 1 .. arr.length - required]
        index = randInt(i+1)
        # Exchange the last unshuffled element with the # selected element; reduces algorithm to O(n) time
        [arr[index], arr[i]] = [arr[i], arr[index]]

      # returns only the slice that we shuffled
      arr[arr.length - required ..]

    # Let's test how evenly distributed it really is
    counter = [0,0,0,0,0,0]
    permutations = ["1,2,3","1,3,2","2,1,3","2,3,1","3,2,1","3,1,2"]
    for i in [1..12000]
      x = shuffle([1,2,3])
      counter[permutations.indexOf("#{x}")] += 1

    alert counter

Post a Comment for "Fischer Yates Shuffle In Coffee-script"