Основные проблемы шифрования/дешифрования на основе ротации

По сути, я слежу за программой Challenge Encryptor лаборатории Jumpstart и столкнулся с некоторыми проблемами.

Вот мой код

class Encryptor
  def cipher(rotation)
    characters = (' '..'z').to_a
    rotated_characters = characters.rotate(rotation)
    Hash[characters.zip(rotated_characters)]
  end

  def encrypt_letter(letter, rotation)
    cipher_for_rotation = cipher(rotation)
    cipher_for_rotation[letter]
  end

  def encrypt(string, rotation)
    letters = string.split("")

    results = letters.collect do |letter|
        encrypt_letter = encrypt_letter(letter, rotation)
    end

    results.join
  end

  def decrypt_letter(letter, rotation)
    cipher_for_rotation = cipher(rotation)
    reversed_cipher = cipher_for_rotation.to_a.reverse.to_h
    reversed_cipher[letter]
  end

  def decrypt(string, rotation)
    letters = string.split("")

    results = letters.collect do |letter|
        decrypt_letter = decrypt_letter(letter, rotation)
    end

    results.join
  end
end

У меня возникают трудности с моим методом расшифровки. Вот следующее наклеено из irb

2.3.0 :001 > load './encryptor.rb'
 => true
2.3.0 :002 > e = Encryptor.new
 => #<Encryptor:0x007fe93a0319b8>
2.3.0 :003 > encrypted = e.encrypt("Hello, World!", 10)
 => "Rovvy6*ay!vn+"
2.3.0 :004 > e.decrypt(encrypted, 10)
 => "\\y%%(@4k(+%x5"

Как видите, при расшифровке моей зашифрованной строки она должна выводить «Hello, World!», то, чем я ее зашифровал, с поворотом 10. Не вижу, что я здесь делаю неправильно, любая помощь будет оценена по достоинству. .


person Sam Lim    schedule 21.02.2017    source источник
comment
Это определенно проблема с моей функцией decrypt_letter. После некоторой отладки в irb проверьте следующее: e.encrypt_letter('t',13) =› & › e.decrypt_letter('&',13) =› 3   -  person Sam Lim    schedule 21.02.2017
comment
Есть ли лучший метод, чем мой метод '.to_a.reverse.to_h'?   -  person Sam Lim    schedule 21.02.2017
comment
Я признаю, что не изучал ваш код глубоко, но тот факт, что ваши методы дешифрования и шифрования выглядят по-разному, является для меня красным флагом. (На самом деле подозрительным является тот факт, что у вас вообще есть два метода.) Насколько я понимаю ваш код, вы реализуете шифр Цезаря, а шифр Цезаря полностью симметричен: шифрование и дешифрование — одно и то же, только с разными ключами. Не должно быть двух методов, и определенно не должно быть двух разных методов для шифрования и дешифрования, поскольку оба они совершенно одинаковы.   -  person Jörg W Mittag    schedule 21.02.2017
comment
@JörgWMittag Большое спасибо за ответ, я просто изучаю основы рубина. Я следую этому руководству: tutorials.jumpstartlab.com/projects/encryptor.html который, я думаю, ведет меня к реализации методов, как вы упомянули, но сначала показывает неправильный способ сделать это? Точно сказать не могу. Обязательно прислушаюсь к вашему совету и проведу дополнительные исследования.   -  person Sam Lim    schedule 21.02.2017
comment
По сути, decrypt(10) совпадает с encrypt(-10), который, в свою очередь, совпадает с encrypt(17) (при условии, что алфавит состоит из 27 букв). В более общем плане decrypt(N) == encrypt(-N) == encrypt(alphabet.size - N).   -  person Jörg W Mittag    schedule 21.02.2017
comment
Я заметил еще одну вещь: cipher_for_rotation.to_a.reverse.to_h. Вы превращаете словарь в массив, переворачиваете массив (т.е. меняете порядок словаря), а затем снова превращаете его в словарь. Но для словарей порядок не имеет значения, так что в итоге вы получите тот же словарь, с которого начали. Чтобы быть более точным: Ruby Hashes do сохраняет порядок вставки ключей и гарантированно выполняет итерацию в этом порядке, поэтому вы сделали обратный порядок вставки (и, следовательно, обратный порядок итерации). Но вы никогда не перебираете хэш, вы получаете доступ только к его значениям.   -  person Jörg W Mittag    schedule 21.02.2017
comment
Так что по сути это NO-OP.   -  person Jörg W Mittag    schedule 21.02.2017


Ответы (1)


Вы можете просто посмотреть ключ хеша.

def decrypt_letter(letter, rotation)
  cipher_for_rotation = cipher(rotation)
  cipher_for_rotation.key(letter)
end

Пример:

irb(main):003:0> e = Encryptor.new
=> #<Encryptor:0x007fbcea9b65c8>
irb(main):004:0> enc = e.encrypt "Hello, World!", 10
=> "Rovvy6*ay!vn+"
irb(main):005:0> e.decrypt enc, 10
=> "Hello, World!"
person rohit89    schedule 21.02.2017
comment
Это может быть именно то, что я искал, спасибо за вклад. Да, это работает отлично. огромное спасибо - person Sam Lim; 21.02.2017