2017-02-21 2 views
0

Ich bin ziemlich neu im Lernen von Ruby und arbeite gerade an Learn to Program von Chris Pine. Eine der Übungen, die er vorschlägt, ist das Schreiben einer Shuffle-Methode (ich kenne die Methode #shuffle). Bisher habe ich mit diesem Code kommen, die die Arbeit zu tun scheint:Eine Shuffle-Methode in Ruby schreiben

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) 

Es ist jedoch ziemlich langatmig überlegen, was es tatsächlich der Fall ist. Kann ich das irgendwie verbessern?

+3

hmmm scheint besser geeignet für http://codereview.stackexchange.com/ – niceman

+0

Möchten Sie um diesen exakten Algorithmus zu implementieren oder möchtest du irgendwie mischen, benutze einfach '# shuffle' nicht? – ndn

+1

@niceman faire genug! Danke für die Information! – Heisenmali

Antwort

2

Ihre Idee ist es, Elemente nach dem Zufallsprinzip auszuwählen, bis Sie alle Elemente ausgewählt haben.

Abgesehen von Ausführlichkeit, ein anderes Problem, das Sie haben, ist, dass Sie #delete verwenden. Wenn sich also zwei sich wiederholende Elemente im Array befinden, erhalten Sie nur eins im gemischten Ergebnis.

Auch mutieren Sie das Array bestanden, was im Allgemeinen unerwünscht ist. Hier ist eine Implementierung des gleichen Algorithmus:

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 

Wie für eine einfachere Lösung:

array.sort_by { rand } 
+0

Das ist großartig, danke! Würde ich richtig sagen, dass das gemischte Array nur innerhalb der Methode existiert, wie auch das Array to_shuffle, von dem die Elemente während jeder Rekursionsrunde gelöscht werden? Das bedeutet ein zweites Array namens to_shuffle, das initiale Array, in dem die Elemente gespeichert sind, bleibt durch die Rekursion unverändert und existiert immer noch außerhalb der Methode? – Heisenmali

+0

@Heisenmali, die Version, die ich geschrieben habe, würde das Array, das du übergeben hast, nicht ändern, wenn du das fragst. Im Allgemeinen sind die Variablen für die Methode lokal und stehen nicht im Konflikt mit externen Variablen. – ndn

+1

Bitte empfehle niemandem das "random sorting shuffle", ohne zu erwähnen, dass es stark voreingenommen und im besten Fall gar nicht einheitlich ist und wirklich völlig kaputt ist: der Komparator verstößt gegen die Grundgesetze einer Vergleichsfunktion und damit die Das Ergebnis der Sortierung ist im Wesentlichen undefiniert. Der einzige korrekte Weg, um ein Shuffle zu implementieren, ist die Verwendung der Durstenfeld-Variante des Fisher-Yates-Algorithmus (bekannt als "Algorithmus P" von Donald Knuth in TAOCP) für das In-Place-Shuffling oder die Inside-Out-Variante für destruktives Mischen. –

Verwandte Themen