Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

アフィン暗号

簡単な暗号法の一つに、アフィン暗号というものがあります。まず、アルファベット a〜z を a = 0, b = 1, c = 2,..., x = 23, y = 24, z = 25 と 0〜25 の数字に置き換えます。そして、以下の式で、原文のアルファベットを置換します。

$F(\gamma) = (\alpha \cdot \gamma + \beta)$ mod $26$

ただし、mod 26 は 26 で割った余りを表します。例えば、$\alpha = 3, \beta = 2$ のとき、アルファベットの 'a' (=0) は、$F(0) = (3 \cdot 0 + 2)$ mod $26 = 2$ で 'c' に、アルファベットの 'n' (=13) は $F(13) = (3 \cdot 13 + 2)$ mod $26 = 15$ で 'p' に置換されます。
このとき、$\gamma$ に対する $F(\gamma)$ が必ず 1 対 1 で対応付けられるように、$\alpha$ と $\beta$ は慎重に選ばれているものとします（$\alpha$ と 26 が互いに素であることが条件）。$\alpha = 4, \beta = 7$ のときのように、$F('a') = 7, F('n') = 7$ と、'a' も 'n' も同じ 'h' に置換されるようなことはありません。また、アルファベット以外の文字は置換されません。

暗号化された文字列を元の文章に復号したものを出力するプログラムを作成してください。元の文章には、キーワードとして

that
this

のいずれかが必ず含まれているものとします。

Input

複数のデータセットが与えられます。１行目にデータセット数 $n$ ($n \leq 30$) が与えられます。続いて $n$ 行のデータが与えられます。各データセットに英小文字と空白からなる 256 文字以内の暗号化された文章が１行に与えられます。

Output

各データセットに対して、復号した元の文章を１行に出力して下さい。

Sample Input

1
y eazqyp pnop pngtg ye obmpngt xmybp mr lygw

Output for the Sample Input

i submit that there is another point of view

Solution in Ruby (judge verdict: Accepted)

# AOJ 0040 Affine Cipher

def decode(s, a_inv, b)
  byte_a = "a".ord

  if s.is_a?(String)
    words = [s]
  elsif s.is_a?(Array)
    words = s
  else
    raise TypeError
  end

  words.map {|word|
    word.bytes.map {|byte|
      d = byte - byte_a
      # 26 を法とすると
      # F(c) \equiv a * c + b は
      # c \equiv a^{-1} * (F(c) - b) と同値
      ((a_inv * (d - b)) % 26 + byte_a).chr
    }.join
  }.join(" ")
end

A_INV = [1, 3, 5, 7, 9, 11, 15, 17, 19, 21, 23, 25]

n = gets.to_i
n.times do
  words = gets.chomp.split
  words_4 = words.select {|word| word.length == 4}

  # 鍵を探す
  a_inv = b = nil
  words_4.each do |word|
    break if a_inv && b

    A_INV.each do |ai|
      break if a_inv && b

      26.times do |b_ai|
        case decode(word, ai, b_ai)
        when "that", "this"
          a_inv, b = ai, b_ai
          break
        end
      end
    end
  end

  puts decode(words, a_inv, b)
end