Я написал функцию, которая берет все элементы с нечетными индексами и объединяет их со всеми элементами с четными индексами в заданной строке n раз:
def encrypt(text,n)
while n > 0
n -= 1
str_array = text.split("")
even_values = str_array.select.with_index { |_, i| i.even? }
odd_values = str_array.select.with_index { |_, i| i.odd? }
text = (odd_values+even_values).join
end
puts text
end
puts 'Type your message to encrypt:'
text = gets
puts 'Type number of times to run encryption:'
n = gets.to_i
encrypt(text,n)
Проблема в том, что если входной текст имеет нечетное количество элементов, функция вернет текст в 2 строки. В то же время, если количество элементов входного текста равно четному, вывод представляет собой 1-строчный текст, чего я и хочу.
Вывод консоли с 10 элементами во входном тексте:
Type your message to encrypt:
abcdefghij
Type number of times to run encryption:
1
bdfhjacegi
Вывод консоли с 11 элементами во входном тексте:
Type your message to encrypt:
abcdefghijk
Type number of times to run encryption:
1
bdfhj
acegik
Для отладочных вопросов требуется код минимальный воспроизводимый пример — вырезать, вставить и запустить, включая наименьший репрезентативный пример ввода в виде кода; желаемый и фактический вывод (включая дословные сообщения об ошибках); теги и версии; четкая спецификация и объяснение. Дайте наименьший код, который вы можете дать, это код, который, как вы показываете, в порядке, расширенный кодом, который, как вы показываете, не в порядке. (Основы отладки.) Найдите первую точку выполнения, в которой состояние переменных отличается от того, что вы ожидаете, и скажите, что вы ожидаете и почему вы ожидаете, обосновав это ссылкой на авторитетную документацию. (Основная отладка.) Как спроситьЦентр помощи
Для n = 1
def doit(str)
enum = [false, true].cycle
str.each_char.partition { enum.next }.map(&:join).join
end
doit "abcdefghij"
#=> "bdfhjacegi"
doit "abcdefghijk"
#=> "bdfhjacegik"
Для n > 1
n.times.reduce(str) { |s,_| doit(s) }
Например:
4.times.reduce(str) { |s,_| doit(s) }
#=>"ejdichbgafk"
См. Перечислимое#уменьшить (он же inject
)
Теперь рассмотрим вычисления, выполненные doit
.
Сначала рассмотрим перечислитель enum
, созданный методом Массив#цикл:
enum = [false, true].cycle
#=> #<Enumerator: [false, true]:cycle>
Мы можем использовать метод Перечислитель#следующий, чтобы увидеть, какие значения будет генерировать этот перечислитель enum
:
enum.next
#=> false
enum.next
#=> true
enum.next
#=> false
... ad infinitum
Теперь сбросим перечислитель с помощью Перечислитель#перемотка назад:
enum.rewind
#<Enumerator: [false, true]:cycle>
Предполагать
str = "abcdefghijk"
Затем
e = str.each_char
#=> #<Enumerator: "abcdefghijk":each_char>
Мы можем преобразовать этот перечислитель в массив, чтобы посмотреть, какие элементы он сгенерирует.
e.to_a
#=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
Продолжая,
a = e.partition { enum.next }
#=> [["b", "d", "f", "h", "j"], ["a", "c", "e", "g", "i", "k"]]
b = a.map(&:join)
#=> ["bdfhj", "acegik"]
b.join
#=> "bdfhjacegik"
Примечание a.map(&:join)
является сокращением от a.map { |arr| arr.join }
.
См. Строка#each_char, Перечислимый#раздел и Массив # присоединиться.
Вам нужно пережевывать ввод, чтобы избавиться от разрыва строки:
text = gets.chomp
разрыв строки включается в вашу объединенную строку между нечетными и четными значениями, когда есть нечетное количество символов