2017-02-21 8 views
0

저는 루비를 배우는 데 새로운 경험이 있습니다. 저는 Chris Pine의 Learn to Program을 배우고 있습니다. 그가 시도한 연습 중 하나는 셔플 메서드를 작성하는 것입니다 (저는 #shuffle 메서드를 알고 있습니다). 지금까지 나는이 코드를 생각해 냈다.이 코드는 작업을 수행하는 것으로 보인다 :루블에 셔플 메서드 작성하기

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 faire enough! 정보 주셔서 감사합니다! – 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 배열처럼 메서드 내에서만 shuffled 배열이 존재한다고 말하는 것이 맞습니까? 이것은 to_shuffle이라는 이름의 두 번째 배열을 의미하며, 요소가 저장된 초기 배열은 재귀에 의해 변경되지 않고 여전히 메서드 외부에 존재합니까? – Heisenmali

+0

@Heisenmali, 내가 쓴 버전은 당신이 요구하는 것이라면 통과 한 배열을 변경하지 않을 것입니다. 일반적으로 변수는 메소드에 대해 지역 변수가되며 외부 변수와 충돌하지 않습니다. – ndn

+1

"무작위 분류 셔플"을 권장하지 마십시오. 편파성이 높고 전혀 균일하지 않으며 실제로는 완전히 깨진 사실을 언급하지 않아도됩니다. 비교 기능은 비교 기능의 기본 법률을 위반하므로 정렬 결과는 본질적으로 정의되지 않습니다. 실제로, 셔플을 구현하는 유일한 올바른 방법은 내부 셔플 링을 위해 Fisher-Yates 알고리즘의 Durstenfeld 변형 (TAOCP의 Donald Knuth에 의해 "Algorithm P"로 대중화 됨)을 사용하는 것입니다. 파괴적인 셔플. –