Module: Proquint
Overview
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.
Constant Summary collapse
- CONSONANTS =
%w[b d f g h j k l m n p r s t v z]
- VOWELS =
%w[a i o u]
- REVERSE =
{}
- DQUAD_PATTERN =
/^(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})$/
- HEX_PATTERN =
/^x(\h+)$/
- VERSION =
"0.0.1"
Instance Method Summary collapse
-
#decode(s, sep = "-") ⇒ Object
Convert a proquint to an array of numbers (between 0 and 0xffff).
- #dquad2hex(dquad) ⇒ Object
-
#encode(i, sep = "-") ⇒ Object
Convert a string, number or array of uint16s to a proquint.
- #hex2dquad(hex) ⇒ Object
- #num2words(num) ⇒ Object
-
#quint2num(s, sep = "-") ⇒ Object
Convert a proquint to a number.
- #words2num(words) ⇒ Object
Instance Method Details
#decode(s, sep = "-") ⇒ Object
Convert a proquint to an array of numbers (between 0 and 0xffff)
79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/proquint.rb', line 79 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) ⇒ Object
24 25 26 27 28 29 30 31 |
# File 'lib/proquint.rb', line 24 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 = "-") ⇒ Object
Convert a string, number or array of uint16s to a proquint
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/proquint.rb', line 61 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) ⇒ Object
33 34 35 36 37 38 39 40 |
# File 'lib/proquint.rb', line 33 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) ⇒ Object
42 43 44 45 46 47 48 49 |
# File 'lib/proquint.rb', line 42 def num2words(num) words = [num & 0xffff] while num > 0xffff num >>= 16 words.unshift(num & 0xffff) end words end |
#quint2num(s, sep = "-") ⇒ Object
Convert a proquint to a number
92 93 94 |
# File 'lib/proquint.rb', line 92 def quint2num(s, sep = "-") words2num(decode(s)) end |
#words2num(words) ⇒ Object
51 52 53 54 55 56 57 58 |
# File 'lib/proquint.rb', line 51 def words2num(words) num = words.shift || 0 until words.empty? num <<= 16 num += words.shift end num end |