2015-08-02 4 views
0

Я работаю над проблемой шифрования Цезаря с левым смещением 1, но с трудом начинаю работать. В приглашении предлагается посмотреть метод String #ord и метод Integer #chr в Ruby Documentation. А буква «а» должен быть перенесен на «г» ...Шифр ​​Цезаря в Ruby

Ниже моя работа ..

def solve_cipher(string, n) 
letters = ['a'..'z'] 
string.map {|x| letters.include?(x.ord + n).chr : x}.join 

Спасибо за любые советы! ...

+0

Ваш вопрос является слишком широким. Пожалуйста, включите результаты своей работы и что не так (что вам действительно нужно конкретно?). Например, вы можете указать, что вы отправляете «ABC» в свою функцию, и он выводит «! $%», Что не так, как вы ожидали, но вы не знаете, почему. – Rots

+2

Добро пожаловать в переполнение стека. При запросе на помощь отладки вам необходимо предоставить образец ввода, ваш ожидаемый результат и минимальный код, необходимый для демонстрации проблемы, возникшей у вас в самом вопросе. Ваш примерный метод не является полным, и нет данных, которые мы можем использовать. Пожалуйста, помогите нам помочь вам и предоставить данные и сделайте метод хотя бы синтаксически правильным. –

ответ

0

Вы должны split свое слово в отдельные символы. Затем вам нужно преобразовать символы в int с ord, чтобы вы могли делать арифметику. Арифметическая операция заключается в добавлении смещения относительно 'a', по модулю 26, так что результат отображает другое смещение от 'a', которое приведет к новому символу. Измените результат на символ с помощью chr и соедините символы вместе, чтобы сформировать строку.

Вот одна из возможных реализаций, которые могут разместиться как верхний и нижний регистр букв:

def shift_char(c, base, offset) 
    (((c.ord - base) + offset) % 26 + base).chr 
end 

def cipher(s, offset) 
    s.chars.map do |c| 
    case c 
    when 'a'..'z' 
     shift_char(c, 'a'.ord, offset) 
    when 'A'..'Z' 
     shift_char(c, 'A'.ord, offset) 
    else 
     c 
    end 
    end.join 
end 

cipher_text = cipher('Now is the time for all good men...', 13) 
p cipher_text  # "Abj vf gur gvzr sbe nyy tbbq zra..." 
original_text = cipher(cipher_text, 13) 
p original_text  # "Now is the time for all good men..." 
+0

Что здесь означают 'c' и 'base'? – jso1226

+0

'c' является индивидуальным символом,' base' является числовой начальной точкой для диапазона букв az или AZ, т. Е. Это '' a'.ord' в первом случае и '' A'.ord' в последний. Например, буква «e» будет первоначально рассчитана как сдвинутая в 4 от «a». Вы можете сделать смещение любым значением, которое вам нравится, но я использовал относительно общее значение 13. Таким образом, добавление смещения от 13 до 'e' теперь отделило бы 17 от «a», которое преобразует его в «r» в шифр.Модуль 26 обертывает любые значения, прошедшие 'z' обратно в начало алфавита. – pjs

+0

Благодарим вас за подробное объяснение. Мне удалось получить короткие сдвиги слов, но когда я вложил длинное предложение, мое командное приглашение возвращает «m <->»? – jso1226

0

Прежде всего, вы должны использовать оператора modulo, чтобы оставаться в диапазоне letters. Во-вторых, вы пытаетесь использовать условный оператор неправильно - читайте около ternary operator. Изменение символов на номера в массиве letters и перемещение его вне функции также будет улучшением. Другая проблема заключается в том, что String не имеет метода map в Ruby. Вы должны использовать метод chars, который возвращает массив символов в вашей строке.

Модифицированная версия вашей solve_cipher функции:

LETTERS = ('a'.ord..'z'.ord) 

def solve_cipher(string, n) 
    string.chars.map {|x| LETTERS.include?(x.ord)?((x.ord - LETTERS.min + n) % 26 + LETTERS.min).chr : x}.join 
end 

Как вы можете видеть, что я взять остаток после деления на 26 - длина LETTERS массива - остаться в диапазоне строчных букв. .

+0

Это не работает. По определению шифр ('z', 1) должен быть равен 'a'. И, очевидно, шифр ('a', -1) должен равняться 'z'. – EugZol

+0

Он работает. Вы можете попробовать сами. solve_cipher ('a', -1) возвращает 'z' и solve_cipher ('z', 1) возвращает 'a'. – Walerian

+0

Yup, теперь он делает: P – EugZol

-1

Вы, вероятно, ищете что-то вроде этого:

def solve_cipher(string, n) 
    string.split('').map do |x| 
    new_index = x.ord + n 
    while new_index > 'z'.ord 
     new_index = 'a'.ord + new_index - 'z'.ord - 1 
    end 
    if new_index < 'a'.ord 
     new_index = 'z'.ord - ('a'.ord - new_index) + 1 
    end 
    new_index.chr 
    end.join 
end 
Смежные вопросы