В настоящее время я изучаю Ruby и попытался выполнить задачу Simple Cipher. Сейчас я изучаю следующее решение и пытаюсь реконструировать, чтобы понять мыслительный процесс, лежащий в основе этого решения. Ниже приведена ссылка на решение. Я подробно расскажу о своем понимании каждого фрагмента кода. Если они не правы, не могли бы вы меня поправить? Спасибо! https://exercism.io/tracks/ruby/exercises/simple-cipher/solutions/b200c3d9f10e497bbe2ca0d826df2661
class Cipher
ALPHABET = [*'a'..'z']
attr_reader :key
def initialize(key = nil)
@key = key || 100.times.map { ALPHABET.sample }.join
fail ArgumentError, 'invalid chars in key' unless valid?(@key)
end
def encode(text)
a = 'a'.ord
text.chars.zip(@key.chars).map do |char, key|
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
end.join
end
def decode(code)
code.chars.zip(@key.chars).map do |char, key|
ALPHABET[char.ord - key.ord]
end.join
end
private
def valid?(key)
!key.empty? && key !~ /[^a-z]/
end
end
Часть 1
@key = ключ - если ключ совпадает. ALPHABET рандомизируется (с помощью метода .sample) и объединяется. Затем рандомизированные объединенные алфавиты повторяются 100 раз, и возвращается новый массив (с методом карты).
Для обработки ошибки недопустимого ключа используется ошибка ArgumentError.
def initialize(key = nil)
@key = key || 100.times.map { ALPHABET.sample }.join
fail ArgumentError, 'invalid chars in key' unless valid?(@key)
end
Часть 2 Я понимаю, что цель этого кода - преобразовать простой текст в зашифрованный. Однако я борюсь с какой-то частью следующего кода.
def encode(text)
a = 'a'.ord
text.chars.zip(@key.chars).map do |char, key|
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
end.join
end
- Метод .ord - преобразует символ в его значение ASCII. a = 'a'.ord. Почему выбран этот персонаж? Не z или другие символы?
- Метод .chars - текстовая строка разделяется на каждый отдельный символ с помощью метода .chars. .chars более эффективен, чем .split, поскольку он анализирует базовые байты для возврата символов строки (я читал разницу между .chars и .split в потоке наложения).
- Метод .zip - этот метод используется для сравнения исходных текстовых символов и символов шифрования.
- Метод .map - этот метод вызывается с блоком и возвращает зашифрованный текст.
Внутри блока метода .map есть два аргумента: char и key. char представляет собой символ из исходного обычного текста, а ключ представляет собой зашифрованный ключевой символ.
У меня проблемы с пониманием этой
ALPHABET[(char.ord - a + key.ord - a) % ALPHABET.length]
части. Исходный обычный текст ALPHABET и текстовые символы ключа шифрования преобразуются в значения ASCII с помощью метода .ord. Почему значение вычитается из этих значений? Зачем использовать оператор% и ALPHABET.length?- Метод .join - я полагаю .join используется для соединения преобразованных зашифрованных символов. Я правильно понимаю?
Часть 3 В этой части используется метод декодирования, код. Код - это секретный ключ, совместно используемый двумя сторонами (отправителем и получателем). Но почему ALPHABET[char.ord - key.ord]
? Символы ascii - ключевое значение ascii предоставит расшифрованный простой текст. Я не понимаю, как это работает?
def decode(code)
code.chars.zip(@key.chars).map do |char, key|
ALPHABET[char.ord - key.ord]
end.join
end
Часть 4 частного метода используется для отделения этого фрагмента кода от других классов. Действительный метод - проверить ключ. Есть два условия: ключ не должен быть пустым или должен состоять из строчных букв.
private
def valid?(key)
!key.empty? && key !~ /[^a-z]/
end