文字列のデクリメント

どこかで知り合いが文字列のデクリメントを作っていた(perl)、インクリメントがあるのにデクリメントがないのは不便だと。
というわけで取り敢えずこんな感じ

('AAA'.reverse.split('').inject_with_index(0){|r,v,i|r + 26**i * v.to_i(36).-(9)}.-(1).-(1).*(-1)...0).inject('A'){ |str,| str.succ }

ここで、inject_with_index は

module Enumerable
  def inject_with_index(result, &proc)
    each_with_index{ |value, index| result = proc.call(result, value, index) }
    return result
  end # def inject_with_index(init, &proc)
end # module Enumerable

数字にするのに to_i(36).-(9) 36進展開(逆展開)してるの注意

Stringのメソッドにするならこんな感じか

class String
  def pred
    (1..(self.reverse.split('').inject_with_index(0){ |r,v,i|r + 26**i * (v.to_i(36) - 9) } - 1 - 1)).inject('A'){ |str, | str.succ }
  end # def pred
end # class String

さっきは一行で書くのに随分技巧的になってる分を直した、それでもまだまだ技巧的か。どちらも二つ目の減算が実際にデクリメントする操作のつもり。
ちなみに入力(レシーバ)が英小文字でも英大文字で答えが返る。英字以外が入ってるときの動作は不明。最初に self.gsub(/[^[:alpha:]]/, '') とかやっといた方が良いかもしれない。