2017-02-21 21 views
0

Я совершенно не знаком с изучением рубинов, и я работаю над программой Learn by Chris Pine. Одно из упражнений, которые он предлагает попробовать, - это написать метод тасования (я знаю метод #shuffle). До сих пор, я пришел с этим кодом, который, кажется, чтобы сделать работу:Написание метода тасования в Ruby

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) 

Однако это довольно многословно, учитывая, что она делает. Есть ли способ улучшить это?

+3

Ммм кажется более подходящим для http://codereview.stackexchange.com/ – niceman

+0

Вы хотите для реализации этого точного алгоритма или вы хотите каким-то образом перетасовать, просто не используйте '# shuffle'? – ndn

+1

@niceman достаточно! Спасибо за информацию! – Heisenmali

ответ

2

Ваша идея - выбрать элементы наугад, пока не выберете все элементы.

В дополнение к многословию другой вопрос, который у вас есть, заключается в том, что вы используете #delete. Следовательно, если в массиве есть два повторяющихся элемента, вы получите только один результат перетасования.

Также вы мутируете переданный массив, что обычно нежелательно. Вот реализация того же алгоритма:

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 

Что касается более простое решение:

array.sort_by { rand } 
+0

Это замечательно, спасибо! Должен ли я быть прав, говоря, что перетасованный массив существует только внутри метода, также как и массив to_shuffle, из которого элементы удаляются во время каждого раунда рекурсии? Это означает, что второй массив, также названный to_shuffle, начальный массив, в котором хранятся элементы, остается неизменным по рекурсии и все еще существует вне метода? – Heisenmali

+0

@Heisenmali, версия, которую я написал, не изменит массив, который вы передали, если это то, о чем вы просите. В общем случае переменные будут локальными для метода и не будут конфликтовать с внешними переменными. – ndn

+1

Пожалуйста, не рекомендуйте «случайную сортировку в случайном порядке» кому-либо, не упоминая о том, что она сильно предвзята и совсем не имеет форму в лучшем случае и действительно просто полностью нарушена: компаратор нарушает основные законы функции сравнения и, следовательно, результат сортировки по существу не определен. Действительно, единственным правильным способом реализации тасования является использование вариации Дурстенфельда алгоритма Фишера-Йейса (популяризированного как «Алгоритм P» Дональда Кнута в TAOCP) для перетасовки на месте или вариант наименьшего из вариантов для не- деструктивная перетасовка. –