Heisenmali
Heisenmali

Reputation: 17

Writing a shuffle method in Ruby

I'm quite new to learning ruby and I am working through Learn to Program by Chris Pine. One of the exercises he suggests to try out is that of writing a shuffle method (I am aware of the #shuffle method). So far, I have come up with this code, which seems to do the job:

array_to_shuffle = []
puts "Give me a list of words to shuffle, press enter on an empty line for the result."
input = gets.chomp

while input != ""
  array_to_shuffle = array_to_shuffle.push(input)
  input = gets.chomp
end

def recursive_shuffle(array_to_shuffle, shuffled_array = [])
  return shuffled_array unless array_to_shuffle.size > 0
  array_size = array_to_shuffle.size()
  random_number = rand(1..array_size)-1
  element_transfered = array_to_shuffle [random_number]
  shuffled_array = shuffled_array.push(element_transfered)
  array_to_shuffle.delete(element_transfered)
  recursive_shuffle(array_to_shuffle, shuffled_array)
end

puts recursive_shuffle(array_to_shuffle)

However, it is quite long-winded considering what it actually does. Is there any way I could improve on this?

Upvotes: 0

Views: 1191

Answers (1)

ndnenkov
ndnenkov

Reputation: 36101

Your idea is to pick elements at random until you have picked all elements.

Other than verbosity, another issue that you have is that you use #delete. Hence if there are two repeating elements in the array, you will get only one in the shuffled result.

Also you mutate the array passed, which is generally undesirable. Here is an implementation of the same algorithm:

def recursive_shuffle(to_shuffle, shuffled = [])
  return shuffled if to_shuffle.empty?
  to_shuffle = to_shuffle.dup if shuffled.empty?

  element = to_shuffle.sample
  to_shuffle.delete_at(to_shuffle.index(element))

  recursive_shuffle(to_shuffle, shuffled + [element])
end

As for a simpler solution:

array.sort_by { rand }

Upvotes: 3

Related Questions