module Proquint

A Proquint is a readable, spellable, pronouncable representation of a number. In Ruby, a proquint is a string, such as “badab-lufiv”, which represents the number 0x407d92 (or 4226450 in decimal).

See arxiv.org/html/0901.4016 for more details.

The main API is provided by ‘encode` and `decode`, the former of which takes a number, or an array of words (unsigned 16-bit integers) to make a proquint, and the latter of which takes a proquint and returns an array of words. There are also some convenience methods for getting a complete number from an array of words, for getting an array of words from a number, and for converting between dotted-decimal IP-addresses and hex IP addresses.

Constants

CONSONANTS
DQUAD_PATTERN
HEX_PATTERN
REVERSE
VERSION
VOWELS

Public Instance Methods

decode(s, sep = "-") click to toggle source

Convert a proquint to an array of numbers (between 0 and 0xffff)

# File lib/proquint.rb, line 83
def decode(s, sep = "-")
  s.split(sep).map do |p|
    p = p.downcase
    raise ArgumentError.new("Invalid proquint") unless p.bytes.length == 5
    (REVERSE[p[0]]   << 12) +
      (REVERSE[p[1]] << 10) +
      (REVERSE[p[2]] << 6) +
      (REVERSE[p[3]] << 4) +
      (REVERSE[p[4]])
  end
end
dquad2hex(dquad) click to toggle source
# File lib/proquint.rb, line 28
def dquad2hex(dquad)
  if dquad =~ DQUAD_PATTERN
    i = (($1.to_i << 24) + ($2.to_i << 16) + ($3.to_i << 8) + $4.to_i)
    "x#{i.to_s(16)}"
  else
    raise ArgumentError.new("Invalid dotted quad")
  end
end
encode(i, sep = "-") click to toggle source

Convert a string, number or array of uint16s to a proquint

# File lib/proquint.rb, line 65
def encode(i, sep = "-")
  case i
    when Fixnum
      raise ArgumentError.new("Can't encode negative numbers") if i < 0
      return encode(num2words(i)) if i > 0xffff
      CONSONANTS[(i & 0xf000) >> 12] +
        VOWELS[(i & 0xc00) >> 10] +
        CONSONANTS[(i & 0x3c0) >> 6] +
        VOWELS[(i & 0x30) >> 4] +
        CONSONANTS[i & 0xf]
    when Array then i.map { |x| encode(x) }.join(sep)
    when DQUAD_PATTERN then encode(dquad2hex(i)[1..-1].to_i(16))
    when String then encode(str2words(i))
    else raise ArgumentError.new("Can't encode #{i}")
  end
end
hex2dquad(hex) click to toggle source
# File lib/proquint.rb, line 37
def hex2dquad(hex)
  if hex =~ HEX_PATTERN
    i = $1.to_i(16)
    [(i & 0xff000000) >> 24, (i & 0xff0000) >> 16, (i & 0xff00) >> 8, i & 0xff].join('.')
  else
    raise ArgumentError.new("Invalid hex address")
  end
end
num2words(num) click to toggle source
# File lib/proquint.rb, line 46
def num2words(num)
  words = [num & 0xffff]
  while num > 0xffff
    num >>= 16
    words.unshift(num & 0xffff)
  end
  words
end
quint2num(s, sep = "-") click to toggle source

Convert a proquint to a number

# File lib/proquint.rb, line 96
def quint2num(s, sep = "-")
  words2num(decode(s))
end
str2words(string) click to toggle source
# File lib/proquint.rb, line 24
def str2words(string)
  string.bytes
end
words2num(words) click to toggle source
# File lib/proquint.rb, line 55
def words2num(words)
  num = words.shift || 0
  until words.empty?
    num <<= 16
    num += words.shift
  end
  num
end