問題
あなたは友達と秘密を共有するために暗号文を作り、その暗号文を元に戻すプログラムを作成することになりました。暗号文を元に戻す際のルールは以下の通りです。
・全ての文は大文字アルファベットのみを使う。
・文字の番号は左から順番に 1 番目から数え始めるものとする。
・暗号文の元に戻す操作として...
奇数番目の文字に対しては、アルファベットの逆方向に N文字ずらし、
偶数番目の文字に対しては、順方向に N 文字ずらしたものにそれぞれ変換する
暗号化された文字列と、元の文をずらした文字数 N が、与えられる
→ 元に戻された文字列を出力するプログラムを作成してください。
ただし、文字をずらした時、アルファベットの先頭、及び末尾をはみ出してしまった場合、
それぞれ、アルファベットの末尾、アルファベットの先頭から続きを数える。
入力される値
入力される値
X
Y
・1 行目には、ずらした文字数を表す整数 X が与えられます。
・2 行には、暗号文字列を表す文字列 Y が与えられます。
入力は 2 行となり、末尾に改行が 1 つ入ります。
・Y は暗号化文字された文字列を表す 英字大文字 からなる文字列
条件
・1 ≦ X ≦ 25
・S は 英字大文字 で構成される文字列。
・1 ≦ (Y の長さ) ≦ 500
例
入力例1
4
QEPG
出力例1
MILK
入力例2
19
KXKPMQVI
出力例2
RQRITJCB
回答
input_lines = readlines.map { _1.chomp }
count = input_lines[0].to_i
word = input_lines[1].chars
array = [*"A".."Z"].map.with_index { |i, num| [i, num] }
answer = []
word.each.with_index(1) do |alph, num|
ans = array.select { |u| u[0] == alph }.flatten
if num % 2 == 1
index = ans[1] - count
elsif num % 2 == 0
index = ans[1] + count
index -= 26 if index > 25
end
answer.push(array.values_at(index).flatten[0])
end
puts answer.join
学び
values_atメソッド
ary = %w( a b c d e )
p ary.values_at( 0, 2, 4 ) #=> ["a", "c", "e"]
p ary.values_at( 3, 4, 5, 6, 35 ) #=> ["d", "e", nil, nil, nil]
p ary.values_at( 0, -1, -2 ) #=> ["a", "e", "d"]
p ary.values_at( -4, -5, -6, -35 ) #=> ["b", "a", nil, nil]
p ary.values_at( 1..2 ) #=> ["b", "c"]
p ary.values_at( 3..10 ) #=> ["d", "e", nil, nil, nil, nil, nil, nil]
p ary.values_at( 6..7 ) #=> [nil, nil]
p ary.values_at( 0, 3..5 ) #=> ["a", "d", "e", nil]
配列のインデックスを指定する事で、配列の要素を柔軟に取り出すメソッド
反省
array = [*"A".."Z"].map.with_index { |i, num| [i, num] }
#=> [["A", 0], ["B", 1]..["Z", 25]]
アルファベットの大文字とそのインデックスを合わせた配列を生成する為に、map
メソッドとwih_index
メソッドを組み合わせて冗長的な方法を選択している。
もっとスタイリッシュに書けそう...