2014-05-19 3 views
1

저는 프로그래머가 아니지만 하나가되고 싶습니다. 그래서 책을 읽었고 튜토리얼을하고 질문을합니다. 다음은 질문입니다.Ruby noobster가 배열을 이해하지 못합니다.

솔리테어 사이퍼 (http://rubyquiz.com/quiz1.html)가있는 루비 퀴즈를하려고합니다. 나는 꽤 잘 작동하는 몇 가지 코드를 썼습니다. 한 점은 프로그램의 끝 부분에 대한 참조가되어야하는 key_deck 배열을 변경한다는 점입니다. 나는이 일이 왜 일어나는 지, 왜 그런지는 모른다.

$characters = Array ('A' .. 'Z') 

def encode to_encode, input_deck 
    trekljdfg = input_deck 
    edeck = input_deck 
    work_string = '' 
    to_encode.upcase.split("").each do |char| 
     if $characters.include?(char) 
      work_string.concat(char) 
     end 
    end 
    work_string = work_string + ('X' * ((5 - (work_string.length % 5)) % 5)) 

    keystream_string = '' 
    while keystream_string.length < work_string.length do # <-- generate keystream 
     edeck = permutation(edeck) 
     keystream_string.concat(get_letter(edeck)) 
    end 

    encoded = combine_with_keystream(work_string, keystream_string) 
    encoded = split_string_in_groups(encoded) 

    return encoded 
end 

def decode to_decode, input_deck 
    ddeck = input_deck 
    to_decode = to_decode.delete(' ') 
    keystream_string = '' 
    while keystream_string.length < to_decode.length do # <-- generate keystream 
     ddeck = permutation(ddeck) 
     keystream_string.concat(get_letter(ddeck)) 
    end 

    array_to_decode = text_to_numbers to_decode 
    array_keystream_string = text_to_numbers keystream_string 
    decoded = '' 
    for i in 0..(array_to_decode.length-1) 
     if array_to_decode[i] >= array_keystream_string[i] 
      decoded.concat($characters[(array_to_decode[i] - array_keystream_string[i])-1]) 
     else 
      decoded.concat($characters[(array_to_decode[i] + 26 - array_keystream_string[i])-1]) 
     end 
    end 

    decoded = split_string_in_groups decoded 

    return decoded 
end 

def permutation deck_to_change 
    deck = deck_to_change 
    def swap array, joker 
     work_array = array 
     joker_position = work_array.index(joker) 
     if joker_position == (work_array.length-1) 
      temp_array = work_array.slice!(1..(work_array.length-2)) 
      work_array = work_array + temp_array 
     else 
      work_array[joker_position], work_array[joker_position+1] = work_array[joker_position+1], work_array[joker_position] 
     end 
     return work_array 
    end 

    deck = swap(deck, 'A') # <-- swap first joker 
    2.times do # <-- swap second joker 
     deck = swap(deck, 'B') 
    end 

    if deck.index('A') < deck.index('B') # <-- triple cut 
     joker_position1 = deck.index('A') 
     joker_position2 = deck.index('B') - joker_position1 
    else 
     joker_position1 = deck.index('B') 
     joker_position2 = deck.index('A') - joker_position1 
    end 
    if joker_position1 == 0 
     temp_array1 = [] 
    else 
     temp_array1 = deck.slice!(0..joker_position1-1) 
    end 
    if joker_position2 == deck.length-1 
     temp_array2 = [] 
    else 
     temp_array2 = deck.slice!(joker_position2+1..deck.length-1) 
    end 
    deck = temp_array2 + deck + temp_array1 

    if (deck.last != 'A') | (deck.last != 'B') # <-- count cut 
     temp_array1 = deck.slice!(0..deck.last.to_i-1) 
     temp_array2 = deck.pop(1) 
     deck = deck + temp_array1 + temp_array2 
    end 
    return deck 
end 

def get_letter deck 
    first = deck.first 
    case first 
    when 'A' 
     first = '53' 
    when 'B' 
     first = '53' 
    end 
    if (deck[first.to_i] == 'A') | (deck[first.to_i] == 'B') 
     return '' 
    else 
     return $characters[((deck[first.to_i]).to_i-1) % 26] 
    end 
end 

def text_to_numbers text 
    array = [] 
    text.upcase.split("").each do |char| 
     array.push($characters.index(char)+1) 
    end 
    return array 
end 

def combine_with_keystream string1, string2 
    temp_array1 = text_to_numbers string1 
    temp_array2 = text_to_numbers string2 

    string = '' 
    for i in 0..(temp_array1.length-1) 
     tmp = temp_array1[i] + temp_array2[i] 
     if tmp > 26 
      tmp = tmp - 26 
     end 
     string.concat($characters[tmp-1]) 
    end 
    return string 
end 

def split_string_in_groups string 
    return string.scan(/.{1,5}/).join(" ") 
end 

#-begin------------------------- 

key_deck = ('1' .. '52').to_a + ['A', 'B'] # <-- this is the key deck ^^ 
string_to_encode = 'Code in Ruby live longer!' # <-- this is the string to be encoded 
string_to_decode = 'GLNCQ MJAFF FVOMB JIYCB' # <-- this is the string to be decoded 
puts "Your encoded text is: #{encode(string_to_encode, key_deck)}" 
puts "Your decoded text is: #{decode(string_to_decode, key_deck)}" 

답변

0

귀하의 permutation 기능은 갑판을 변경 :

여기 내 noobish 코드입니다. 원래 데크에 대한 참조를 전달하므로 참조에서 변경하면 실제로 원본이 변경됩니다. 대신이 같은 것을보십시오 :

key_deck = [....] 
... 
puts "#{encode(string_to_encode, key_dec.clone}" 

clone 방법을 사용하여 모든 변경 사항은 사본에 적용됩니다에 대한 배열의 새 복사본을 만들 것입니다.

아니면 그냥 Array#shuffle 방법을 사용하여 전체 문제를 avoit 수 있습니다 다음 encode 함수에 이미 단행 갑판을 줄 것이다

puts "#{encode(string_to_encode, key_dec.shuffle}" 

.

+0

감사합니다. 두 번째 제안 정보 : 원래 구성에서 사용할 데크가 필요합니다. –

0

입력 배열을 변경하는 데크의 순열을 찾으려면 slice!을 사용하고 있습니다.

가장 쉬운 해결책은 배열이 작업을 시작하기 전에 dup이다 :

def encode to_encode, input_deck 
    trekljdfg = input_deck.dup 
    edeck = input_deck.dup 
    # .. 
end 

def decode to_decode, input_deck 
    ddeck = input_deck.dup 
    # .. 
end 

dup는 안전하게 자르다 수있는 배열의 복사본을 만듭니다.

+0

나는 본다. 도와 줘서 고마워. 즉 추측 할 수 있었다, 그러나 그것은 너무이 wariable로 발생하는 이유 : 는'code'는 change_text 텍스트 1 \t 텍스트 1 = '변경 텍스트' \t 반환 텍스트 1 끝 텍스트 = '원문은' change_text 텍스트 텍스트를 데프두고 'code' –

+0

이 코드에서는 _reference_ ('text1 = ...')의 값을 변경했습니다. 'slice!'(http://ruby-doc.org/core-2.0.0/Array.html#method-slice-21)와 같은 API를 사용하면 _object 자체가 _ 대신 변경됩니다. 참조를 보유하고있는 사람이 볼 수 있습니다. 'text1.gsub! ('i', 'I')'를 시도하고 무슨 일이 일어나는 지보십시오. –

관련 문제