LoginSignup
14
13

More than 5 years have passed since last update.

36進数でちょっと遊ぶ (簡単な英文を書く)

Last updated at Posted at 2014-03-14

16進数は[a-f]までですが、36進数なら全てのアルファベットを使えます
英単語なら完全に数値として読めます

10進数との相互変換

Ruby
"apple".to_i(36) #=>17995730

17995730.to_s(36) #=>"apple"
JavaScript
parseInt("apple", 36) //=>17995730

(17995730).toString(36) //=>"apple"

「apple」という単語が書かれているのでは無い
「17995730」という10進数の36進表記なのだ...

JavaScriptの整数の計算誤差について

JavaScriptの場合、桁数が多いと誤差が出ます
自然数の場合は2^53 (9,007,199,254,740,992)までなら問題無いです

記号も使いたい

36進数の文字種は0-9の数値と、a-zのアルファベットのみです

記号を使いたい場合、記号リストを用意して、0-9に割り当てて置換します
これで簡単な英文なら表現できます

lm.rb
base10 = 121448246333169538562105956741709730840134098137499009964148600669661648586559384734426780238529123084195348

base36 = base10.to_s(36)
#=> "i0thought0what0i1d0do0was20i1d0pretend0i0was0one0of0those0deaf3mutes4"

symbols = " ',-."

puts base36.gsub(/[0-9]/){|d|symbols[d.to_i]}
#=> "i thought what i'd do was, i'd pretend i was one of those deaf-mutes."

最初はbase36.tr("0-9", symbols)としてましたが「^-\」を含んでいた場合にうまく変換できない可能性があるのでgsubにしました
(エスケープするにしても結局gsubしなければならないと思うので)

記号含めて変換する

base36utils.rb
module Base36Utils
  def get_symbols(str)
    syms = str.scan(/[^a-zA-Z]/).uniq.sort.join
  end

  def to_base36(base10, symbols="")
    base10.to_s(36).gsub(/[0-9]/){|d|symbols[d.to_i]}
  end

  def to_base10(base36, symbols="")
    base36.gsub(/[^a-zA-Z]/){|c|symbols.index(c)}.to_i(36)
  end
end
sample.rb
require_relative 'base36utils'

include Base36Utils

str = "You know what I'd like to be? I mean if I had my goddamn choice, I'd just be the catcher in the rye and all."

syms = get_symbols(str)

base10 = to_base10(str, syms)
base36 = to_base36(base10, syms)

print "original: "; p str
#=> "You know what I'd like to be? I mean if I had my goddamn choice, I'd just be the catcher in the rye and all."
print "symbols: "; p syms
#=> " ',.?"

puts
puts "encoded (base10): "; p base10
#=> 1160298464533611188100561590112133834453448123656789220667590285674166764197329933937388578689862569716412816858127688041239872565463587711302882017935722749774989021127

puts "decoded (base36): "; p base36
#=> "you know what i'd like to be? i mean if i had my goddamn choice, i'd just be the catcher in the rye and all."

アンダーバー

Rubyの場合、36進数の文字列にアンダーバーを入れても読んでくれます
(ただの目印なので10進数に変換したら元に戻す方法はありません)

double_compile.rb
num = "double_compile".to_i(36) #=>64868740571137744994

puts num.to_s(36) #=> "doublecompile" 

参考

Wikipedia: Base 36

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13