何をしたいのか
業務で書いたコードなのだが、作成する元になったアイディアがボツになったため、お蔵入り。需要は無いだろうけど、せっかくなので当時、ググっても出てこなかったので公開しておこうと思う。1から始まる任意の数字をASCII
で定義されている数値と文字の紐付け表からa
からz
の適切な小文字アルファベット(半角英字)に変換するという処理だ。for
で生成されるiteration
のカウントを使ってa-zの文字列を生成するために使用していた。言葉で伝えても分かりづらいので動作の例を下記に記す
i = 1 -> a i = 2 -> b : i = 26 -> z i = 27 -> a i = 28 -> b : :
業務ではgolang
を使って記述したのだが、せっかくなのでElixir
で書き直した
予備知識
アルファベットとはご存知の通り、a-zで合計26文字が定義されている。またASCII
では小文字のa
を97
、小文字のz
を122
として定義している。つまりは、26回周期でまた同じ半角英字が現れるということになる
アルファベット番号 | ASCII番号 |
---|---|
a | 97 |
b | 98 |
z | 122 |
実際のコード
golang
// 数値をasillに変換する関数(eg: 97 -> a, 122 -> z) func IntToASCII(num int) int { // 26 -> アルファベットの数 if num > 26 { div := num / 26 // 割り切れる際に整合性を取るため-1 if num%26 == 0 { div -= 1 } num -= 26 * div } // aが97で始まるため+97 return num + 96 }
実行結果
package main import ( "fmt" ) func main() { for i := 1; i < 100; i++ { res := IntToASCII(i) fmt.Println("i = ", i, ", res = ", res, ", str = ", string(res)) } }
i = 1 , res = 97 , str = a i = 2 , res = 98 , str = b i = 3 , res = 99 , str = c : i = 24 , res = 120 , str = x i = 25 , res = 121 , str = y i = 26 , res = 122 , str = z i = 27 , res = 97 , str = a i = 28 , res = 98 , str = b : i = 51 , res = 121 , str = y i = 52 , res = 122 , str = z i = 53 , res = 97 , str = a i = 54 , res = 98 , str = b : i = 95 , res = 113 , str = q i = 96 , res = 114 , str = r i = 97 , res = 115 , str = s i = 98 , res = 116 , str = t i = 99 , res = 117 , str = u
全文のコード詳細な結果はこちら
play.golang.org
Elixir
ゴリ押し感はいなめない。こういう計算処理を関数型でゴリゴリ書こうとするとどうなるんだろうと考えさせられた
# 無名関数を定義 int_to_ASCII = fn num -> if num > 26 do num - (div(num, 26) + if(rem(num, 26)==0, do: -1, else: 0)) * 26 + 96 else num + 96 end end
実行結果
Enum.each(1..100, fn n -> res = int_to_ASCII.(n) IO.puts("i = #{n}, res = #{res}, str = #{[res]}") end)
i = 1, res = 97, str = a i = 2, res = 98, str = b i = 3, res = 99, str = c i = 4, res = 100, str = d : : i = 97, res = 115, str = s i = 98, res = 116, str = t i = 99, res = 117, str = u i = 100, res = 118, str = v
無名関数を使わないver
こっちの方がElixir
っぽいかな
defmodule ASCII do def from_int(num) when num > 26 do num - calc_helper(num) * 26 + 96 end def from_int(num), do: num + 96 def calc_helper(num) do if rem(num, 26) == 0 do div(num, 26) -1 else div(num, 26) end end end
おまけ
Elixir
のコードを後日さらにコンパクトに改良
defmodule ASCII do def from_int(num) when num > 26 do num - calc_helper(num) * 26 + 96 end def from_int(num), do: num + 96 def calc_helper(num) when rem(num, 26) == 0, do: div(num, 26) -1 def calc_helper(num), do: div(num, 26) end