module Integer::Base

Constants

ENCODED_CROCKFORD_BASE32_CHARS

Crockford’s Base32. Excluded I, L, O, U. @see www.crockford.com/base32.html

SPECIAL_CHAR_PATTERN

@return [Regexp]

STANDARD_CHARS

@return [Hash] @example

{ 1  => [:"0"],
  2  => [:"0", :"1"],
  36 => [:"0", :"1", ... , :Z] }
VERSION

Public Class Methods

integer_for_string(str, positional_chars) click to toggle source

@param [String, to_str] str @param [Array<Symbol, String, to_sym>] positional_chars @return [Integer]

# File lib/integer/base/singleton_class.rb, line 10
def integer_for_string(str, positional_chars)
  str = str.to_str.downcase

  sign = parse_sign!(str)
  abs = (
    case positional_chars.length
    when 1
      parse_unary_abs(str, positional_chars.first)
    else
      parse_positional_abs(str, positional_chars)
    end
  )

  (sign == :-) ? -abs : abs
end
Also aliased as: parse
parse(str, positional_chars)
Alias for: integer_for_string
string_for(num, positional_chars)
Alias for: string_for_integer
string_for_integer(num, positional_chars) click to toggle source

@param [Integer, to_int] num @param [Array<Symbol, String, to_sym>] positional_chars @return [String]

# File lib/integer/base/singleton_class.rb, line 31
def string_for_integer(num, positional_chars)
  case positional_chars.length
  when 1
    string_unary_for(num, positional_chars.first)
  else
    string_positional_for(num, positional_chars)
  end
end
Also aliased as: string_for

Private Class Methods

base_chars_for(chars) click to toggle source

@param [Array<#to_sym>] chars @return [Array<Symbol>]

# File lib/integer/base/singleton_class.rb, line 61
def base_chars_for(chars)
  chars = chars.map { |c| c.downcase.to_sym }

  case
  when chars.length < 2
    raise TypeError, 'use 2 or more than characters'
  when chars.dup.uniq!
    raise InvalidCharacterError, 'duplicated characters'
  when chars.any? { |s| s.length != 1 }
    raise InvalidCharacterError,
          'chars must be Array<Char> (Char: length 1)'
  when chars.any? { |c| SPECIAL_CHAR_PATTERN =~ c }
    raise InvalidCharacterError,
          'included Special Characters (-, +, space, control-char)'
  else
    chars
  end
end
parse_positional_abs(str, chars) click to toggle source

@return [Integer]

# File lib/integer/base/singleton_class.rb, line 94
def parse_positional_abs(str, chars)
  raise InvalidCharacterError, 'given str is empty' if str.empty?

  base = chars.length
  chars = base_chars_for(chars)

  str = str.dup
  trim_positional_paddings!(str, chars.first)

  str.chars.reverse_each.with_index.inject(0) { |sum, char_index|
    char, index = *char_index

    if radix = chars.index(char.to_sym)
      sum + (radix * (base ** index))
    else
      raise InvalidCharacterError, "#{char} is not defined on #{chars}"
    end
  }
end
parse_sign!(str) click to toggle source

@return [Symbol]

# File lib/integer/base/singleton_class.rb, line 45
def parse_sign!(str)
  sign = str.slice!(/\A([-+])/, 1)

  if sign
    if str.empty?
      raise InvalidCharacterError, 'given string does not have characters except +/-'
    else
      sign.to_sym
    end
  else
    :+
  end
end
parse_unary_abs(str, char) click to toggle source

@return [Integer]

# File lib/integer/base/singleton_class.rb, line 115
def parse_unary_abs(str, char)
  char = unary_char_for(char)
  return 0 if str.empty?

  chars = str.chars.to_a

  atoms = chars.uniq
  unless atoms.length == 1
    raise InvalidCharacterError, 'contain multiple chars'
  end

  atom = atoms.first.to_sym
  unless atom == char
    raise InvalidCharacterError, 'not match the char and atom'
  end

  chars.length
end
string_positional_for(num, chars) click to toggle source

@return [String]

# File lib/integer/base/singleton_class.rb, line 135
def string_positional_for(num, chars)
  chars = base_chars_for(chars)
  int   = num.to_int
  base  = chars.length

  return chars.first.to_s if int == 0

  (+'').tap { |s|
    n = int.abs

    until (n, excess = n.divmod(base); n == 0 && excess == 0)
      s << chars[excess].to_s
    end

    s.reverse!
    s.insert(0, '-') if int < 0
  }
end
string_unary_for(num, char) click to toggle source

@return [String]

# File lib/integer/base/singleton_class.rb, line 155
def string_unary_for(num, char)
  char = unary_char_for(char)
  int = num.to_int

  (char.to_s * int.abs).tap { |s|
    s.insert(0, '-') if int < 0
  }
end
trim_positional_paddings!(str, pad_char) click to toggle source
# File lib/integer/base/singleton_class.rb, line 89
def trim_positional_paddings!(str, pad_char)
  str.slice!(/\A#{Regexp.escape(pad_char)}+/)
end
unary_char_for(char) click to toggle source

@return [Symbol]

# File lib/integer/base/singleton_class.rb, line 81
def unary_char_for(char)
  unless (char.length == 1) && char.respond_to?(:to_sym)
    raise InvalidCharacterError, "#{char.inspect} must be 1 character and can be symbolized"
  end

  char.to_sym
end