module Nth
Constants
- FRACTION_UTF
- NUMBERS
- ORDINALS
might go to just under Duomillinillion, but not until next revision to go higher, need the definitive naming scheme.
- ORD_FORMAT_ERROR
NUMBERS.each_pair { |key,val| ords = val + “th” if ords.nil? }
ORDINALS
= ords.freeze- PLURAL_EXCPETIONS
- PRE_TABLE
- SET_NOVE
- SET_TRE
- VERSION
Public Class Methods
calculate_prefix(str)
click to toggle source
# File lib/nth.rb, line 272 def self.calculate_prefix(str) # see: https://en.wikipedia.org/wiki/Names_of_large_numbers raise ORD_FORMAT_ERROR unless str.index('ii').nil? str = str.dup m = 0 if (str[0..4]=='milli') m = 1000 str = str[5..-1] end n = 0 pre, props = lookup_prefix(str) raise ORD_FORMAT_ERROR if pre.nil? if props[:val] < 10 n += props[:val] if props[:if].empty? # simple case str = str[pre.length..-1] pre, props = lookup_prefix(str) else # tricky case str = str[pre.length..-1] pre, sfx = lookup_prefix(str) if pre.nil? xs = str[0] str = str[1..-1] pre, sfx = lookup_prefix(str) raise ORD_FORMAT_ERROR if pre.nil? ch = (props[:if] & sfx[:rpl]).first.to_s unless ch==xs ch = ch.to_sym raise ORD_FORMAT_ERROR unless props[:if].include? ch raise ORD_FORMAT_ERROR unless props[:sfx].include? xs.to_sym end else raise ORD_FORMAT_ERROR unless (props[:if] & sfx[:rpl]).empty? end props = sfx end end if pre && (props[:val] < 100) str = str[pre.length..-1] n += props[:val] pre, sfx = lookup_prefix(str) if pre.nil? ch = str[0] str = str[1..-1] pre, sfx = lookup_prefix(str) unless pre.nil? cch = (sfx[:rpl] & props[:sfx]).first.to_s raise ORD_FORMAT_ERROR unless cch == ch end props = sfx end end if pre && (props[:val] < 1000) str = str[pre.length..-1] n += props[:val] pre, sfx = lookup_prefix(str) raise ORD_FORMAT_ERROR unless pre.nil? # too many! end n += m raise ORD_FORMAT_ERROR if n <= 10 n *= 3 n = 10 ** (n+3) return n end
create_big_number_name(mult)
click to toggle source
# File lib/nth.rb, line 455 def self.create_big_number_name(mult) pre = "" num = (mult-3) / 3 if (num >= 1000) idx = "10**#{mult}" rtn = NUMBERS[idx] return rtn unless rtn.nil? pre = "milli" num -= 1000 raise "Number too big" if num >= 1000 # next revision may address larger numbers end huns, dec = num.divmod 100 tens, ones = dec.divmod 10 str = "" unless ones.zero? if (1==ones) str = "un" elsif (2==ones) str = "duo" elsif (3==ones) str = "tre" if [2,3,4,5,8].include? tens str += 's' elsif tens.zero? if [1,3,4,5,8].include? huns str += 's' end end elsif (4==ones) str = "quattuor" elsif (5==ones) str = "quinqua" elsif (6==ones) str = "se" if [2,3,4,5].include? tens str += 's' elsif 8==tens str += 'x' elsif tens.zero? if [3,4,5].include? huns str += 's' elsif [1,8].include? huns str += 'x' end end elsif (7==ones) str = "septe" if [1,8].include? tens str += 'm' elsif [1,3,4,5,6,7].include? tens str += 'n' elsif tens.zero? if (1..7).include? huns str += 'n' elsif 8 == huns str += 'm' end end elsif (8==ones) str = "octo" elsif (9==ones) str = "nove" if [1,8].include? tens str += 'm' elsif [1,3,4,5,6,7].include? tens str += 'n' elsif tens.zero? if (1..7).include? huns str += 'n' elsif 8 == huns str += 'm' end end end end unless tens.zero? if (1==tens) str += 'dec' str += 'i' unless huns.zero? elsif (2==tens) str += 'vigint' str += 'i' unless huns.zero? elsif (3==tens) str += 'trigint' str += 'a' unless huns.zero? elsif (4==tens) str += 'quadragint' str += 'a' unless huns.zero? elsif (5==tens) str += 'quinquagint' str += 'a' unless huns.zero? elsif (6==tens) str += 'sexagint' str += 'a' unless huns.zero? elsif (7==tens) str += 'septuagint' str += 'a' unless huns.zero? elsif (8==tens) str += 'octogint' str += 'a' unless huns.zero? elsif (9==tens) str += 'nonagint' str += 'a' unless huns.zero? end end unless huns.zero? if (1==huns) str += 'cent' elsif (2==huns) str += 'ducent' elsif (3==huns) str += 'trecent' elsif (4==huns) str += 'quadringent' elsif (5==huns) str += 'quingent' elsif (6==huns) str += 'sescent' elsif (7==huns) str += 'septingent' elsif (8==huns) str += 'octingent' elsif (9==huns) str += 'nongent' end end return pre + str + 'illion' end
get_denominator_name(int)
click to toggle source
# File lib/nth.rb, line 688 def self.get_denominator_name(int) return "half" if 2==int return "quarter" if 4==int return get_ordinal_name(int, :-) end
get_n_from_array(ary)
click to toggle source
these may need to be redone …
# File lib/nth.rb, line 411 def self.get_n_from_array(ary) if("minus"==ary.first) n = get_n_from_array(ary[1..-1]) return nil if n.nil? return -n end a = lookup_number(ary[0]) if a.nil? a = lookup_ordinal(a[0]) return nil if a.nil? raise ORD_FORMAT_ERROR if is ary.size > 1 return a end b = lookup_number(ary[1]) if b.nil? b = lookup_ordinal(ary[1]) raise ORD_FORMAT_ERROR if b.nil? raise ORD_FORMAT_ERROR unless ary[2].nil? if a > b # forty_fourth else end else end nil end
get_n_from_string(ordinal)
click to toggle source
# File lib/nth.rb, line 437 def self.get_n_from_string(ordinal) n = lookup_ordinal(ordinal) return n unless n.nil? return get_n_from_array(ordinal.split('_')) end
get_number_name(int, *flags)
click to toggle source
# File lib/nth.rb, line 584 def self.get_number_name(int, *flags) ary = get_number_struct(int) neg = ary.pop == :neg return NUMBERS[0] if ary.empty? ary.reverse! mult = 0 str = "" ch = flags.include?(:_) ? "_" : " " tch = flags.include?(:-) ? "-" : ch loop do break if ary.empty? num = ary.pop hun, dec = num.divmod 100 tstr = "" unless hun.zero? tstr = NUMBERS[hun] + ch + NUMBERS[100] unless dec.zero? tstr += ch end end unless dec.zero? if NUMBERS[dec].nil? tens, ones = dec.divmod 10 tstr += NUMBERS[tens*10] + tch + NUMBERS[ones] else tstr += NUMBERS[dec] end end unless tstr.empty? if mult.zero? str = tstr else ms = "10**#{mult}" mm = NUMBERS[ms] # if you run out, you will need a generator mm = create_big_number_name(mult) if mm.nil? if str.empty? str = tstr + ch + mm else str = tstr + ch + mm + ch + str end end end mult += 3 end if flags.include? :plus_minus if neg # use default return "minus" + ch + str end return "plus" + ch + str end if flags.include? :positive_negative if neg # use default return "negative" + ch + str end return "positive" + ch + str end if neg # use default return "minus" + ch + str end return str end
get_number_struct(int)
click to toggle source
# File lib/nth.rb, line 444 def self.get_number_struct(int) neg = int < 0 int = -int if neg dat = [] while(int > 0) int, triplet = int.divmod 1000 dat.push triplet end dat.push neg ? :neg : :pos end
get_ordinal_name(int, *flags)
click to toggle source
# File lib/nth.rb, line 646 def self.get_ordinal_name(int, *flags) return ORDINALS[0] if int.zero? ch = flags.include?(:_) ? "_" : " " tch = flags.include?(:-) ? "-" : ch if int.negative? if flags.include? :positive_negative pre = "negative" + ch else flags.include? :plus_minus pre = "minus" + ch end else if flags.include? :positive_negative pre = "positive" + ch elsif flags.include? :plus_minus pre = "plus" + ch else pre = "" end end flags = flags - [:positive_negative, :plus_minus] int = int.abs n1,n2 = int.divmod 100 unless n2.zero? n1 *= 100 if n1.zero? str = pre else str = pre + get_number_name(n1, *flags) str += ch end if ORDINALS.include? n2 str += ORDINALS[n2] return str end n1,n2 = n2.divmod 10 n1 *= 10 str += NUMBERS[n1] + tch + ORDINALS[n2] return str end return pre + get_number_name(int, *flags) + "th" end
install(pn = :None, *plist)
click to toggle source
# File lib/nth.rb, line 1009 def self.install(pn = :None, *plist) if (pn==:IntMethods) Integer.class_eval do unless self.instance_methods.include? :nth def nth(comma=true) Nth::IntMethods.to_nth_string(self, comma) end end unless self.instance_methods.include? :to_ordinal def to_ordinal Nth::IntMethods.to_ordinal_string(self) end end unless self.instance_methods.include? :to_number def to_number Nth::IntMethods.to_number_string(self) end end unless self.instance_methods.include? :cents_to_dollars def cents_to_dollars Nth::IntMethods.penny_to_dollar(self) end end unless self.instance_methods.include? :pence_to_pounds def pence_to_pounds Nth::IntMethods.pence_to_pound(self) end end end # add to wrapper classes ... meths = [:nth, :to_ordinal, :to_number, :cents_to_dollars, :pence_to_pounds] Int.bestow_methods(*meths) Number.bestow_methods(*meths) Datum.bestow_methods(*meths) elsif (pn==:FloatMethods) Float.class_eval do unless self.instance_methods.include? :to_fractional_unit def to_fractional_unit(unit_name, mode = :descriptive, tar=0.01) Nth::FloatMethods.to_fractional_unit(self, unit_name, mode, tar) end end unless self.instance_methods.include? :inches_to_feet def inches_to_feet(mode = :descriptive, denom=16) Nth::FloatMethods.inches_to_feet(self, mode, denom) end end unless self.instance_methods.include? :inches_to_yards def inches_to_yards(mode = :descriptive, denom=16) Nth::FloatMethods.inches_to_yards(self, mode, denom) end end unless self.instance_methods.include? :to_dms def to_dms(sec_frac=2) Nth::FloatMethods.to_dms(self, sec_frac) end end end elsif (pn==:AccessAllOrdinals) plist[0].class_eval do @default_insert = plist[1] if @default_insert.nil? if self==String @default_insert = ' ' end end def respond_to_missing?(method_name, include_private = false) begin meth = method_name.to_s str = meth[-1]=="=" ? meth[0..-2] : meth num = Nth::ordinal_string_to_number(str) return num.type_of? Integer rescue return false end return false end def method_missing(method_name, *prms, &block) meth = method_name.to_s num = nil assign = false str = "" begin if meth[-1]=="=" str = meth[0..-2] assign = true else str = meth end num = Nth::ordinal_string_to_number(str) rescue super end super if num.nil? if assign if 1==prms.count if num >= size rpl = self.class.instance_variable_get :@default_insert (size..(num-1)).each { |t| self[t] = rpl } end self[num] = prms[0] return self else raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 1)" end else raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 0)" if prms.count > 0 return self[num] end end end elsif (pn==:AccessOrdinals) plist[0].class_eval do @default_insert = plist[2] if @default_insert.nil? if self==String @default_insert = ' ' end end unless self.instance_methods.include? :last def last self[-1] end end unless self.instance_methods.include? :last= def last=(val) self[-1]=val end end ran = (1..plist[1]) ran.each do |num| meth = Nth::get_ordinal_name(num, :_) unless self.instance_methods.include? meth.to_sym define_method meth.to_sym do self[num-1] end end meth += '=' unless self.instance_methods.include? meth.to_sym define_method meth.to_sym do |val| if num >= size rpl = self.class.instance_variable_get :@default_insert (size..(num-1)).each { |t| self[t] = rpl } end self[num-1] = val self end end end end else raise "unrecognized install parameter #{pn}" end end
lookup_number(num)
click to toggle source
this only looks up a single item… need to expand for other prefixes/
# File lib/nth.rb, line 337 def self.lookup_number(num) return eval(NUMBERS.key(num).to_s) if (NUMBERS.values.include? num) if ("illion" == num[-6..-1]) # str = num[0..-7] return calculate_prefix(num) end return nil end
lookup_ordinal(ordinal)
click to toggle source
# File lib/nth.rb, line 346 def self.lookup_ordinal(ordinal) return 0 if (ordinal=="last") return eval(ORDINALS.key(ordinal).to_s) if (ORDINALS.values.include? ordinal) str = ordinal[0..-3] return lookup_number(str) end
lookup_prefix(str)
click to toggle source
# File lib/nth.rb, line 235 def self.lookup_prefix(str) if (PRE_TABLE.include? str[0..11]) return [str[0..11], PRE_TABLE[str[0..11]]] end if (PRE_TABLE.include? str[0..10]) return [str[0..10], PRE_TABLE[str[0..10]]] end if (PRE_TABLE.include? str[0..9]) return [str[0..9], PRE_TABLE[str[0..9]]] end if (PRE_TABLE.include? str[0..8]) return [str[0..8], PRE_TABLE[str[0..8]]] end if (PRE_TABLE.include? str[0..7]) return [str[0..7], PRE_TABLE[str[0..7]]] end if (PRE_TABLE.include? str[0..6]) return [str[0..6], PRE_TABLE[str[0..6]]] end if (PRE_TABLE.include? str[0..5]) return [str[0..5], PRE_TABLE[str[0..5]]] end if (PRE_TABLE.include? str[0..4]) return [str[0..4], PRE_TABLE[str[0..4]]] end if (PRE_TABLE.include? str[0..3]) return [str[0..3], PRE_TABLE[str[0..3]]] end if (PRE_TABLE.include? str[0..2]) return [str[0..2], PRE_TABLE[str[0..2]]] end if (PRE_TABLE.include? str[0..1]) return [str[0..1], PRE_TABLE[str[0..1]]] end return [nil,nil] end
num_ord_string_to_ary(str)
click to toggle source
# File lib/nth.rb, line 353 def self.num_ord_string_to_ary(str) return str.split('_') if str.index(' ').nil? # underscore format ary = [] aaa = str.split ' ' aaa.each do |elm| ary += elm.split '-' end return ary end
number_string_to_number(str_ary)
click to toggle source
# File lib/nth.rb, line 363 def self.number_string_to_number(str_ary) sum = 0 psum = 0 neg = false if str_ary.kind_of? String ary = num_ord_string_to_ary(str_ary) else ary = str_ary end ary.each do |elm| if elm == 'minus' neg = true break end num = lookup_number(elm) return nil if num.nil? if num < 1000 if psum==0 psum = num elsif num > psum psum *= num else psum += num end else sum += num * psum psum = 0 end end sum += psum sum = -sum if neg return sum end
ordinal_string_to_number(str)
click to toggle source
# File lib/nth.rb, line 397 def self.ordinal_string_to_number(str) return -1 if str=="last" sum = 0 ary = num_ord_string_to_ary(str) nth = ary.pop val = lookup_ordinal(nth) return nil if val.nil? ary.push get_number_name(val).split(' ').last num = number_string_to_number(ary) return nil if num.nil? return num-1 end
pluralize(str)
click to toggle source
utility methods: the gem pluralize too simple … maybe you should fix this …
- ::TODO
-
move to new gem, then update this gem
# File lib/nth.rb, line 205 def self.pluralize(str) str = str.rstrip tst = PLURAL_EXCPETIONS[str] return tst unless tst.nil? ch = str[-1] sfx = str[-2..-1] if ['ay','ey','oy','uy','iy'].include? sfx return str + 's' elsif ['is'].include? sfx # analysis analyses return str[0..-3] +'es' elsif ['us'].include? sfx # focus foci return str[0..-3] +'i' elsif sfx=='fe' return str[0..-3] + 'ves' elsif ch=='f' return str[0..-2] + 'ves' elsif ch=='y' return str[0..-2] +'ies' elsif ['s','x','z','o'].include? ch return str +'es' elsif ['ch', 'sh'].include? sfx return str +'es' elsif ['um'].include? sfx # datum data return str[0..-3] +'a' #elsif ['on'].include? sfx # criterion criteria <<< more the exception than the rule # return str[0..-2] +'a' unless str[-3]=='o' # moon, spoon ... pion peon son won ton end return str + 's' end
Public Instance Methods
cents_to_dollars()
click to toggle source
# File lib/nth.rb, line 1028 def cents_to_dollars Nth::IntMethods.penny_to_dollar(self) end
inches_to_feet(mode = :descriptive, denom=16)
click to toggle source
# File lib/nth.rb, line 1051 def inches_to_feet(mode = :descriptive, denom=16) Nth::FloatMethods.inches_to_feet(self, mode, denom) end
inches_to_yards(mode = :descriptive, denom=16)
click to toggle source
# File lib/nth.rb, line 1056 def inches_to_yards(mode = :descriptive, denom=16) Nth::FloatMethods.inches_to_yards(self, mode, denom) end
last()
click to toggle source
# File lib/nth.rb, line 1128 def last self[-1] end
last=(val)
click to toggle source
# File lib/nth.rb, line 1133 def last=(val) self[-1]=val end
method_missing(method_name, *prms, &block)
click to toggle source
Calls superclass method
# File lib/nth.rb, line 1085 def method_missing(method_name, *prms, &block) meth = method_name.to_s num = nil assign = false str = "" begin if meth[-1]=="=" str = meth[0..-2] assign = true else str = meth end num = Nth::ordinal_string_to_number(str) rescue super end super if num.nil? if assign if 1==prms.count if num >= size rpl = self.class.instance_variable_get :@default_insert (size..(num-1)).each { |t| self[t] = rpl } end self[num] = prms[0] return self else raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 1)" end else raise "*** ArgumentError Exception: wrong number of arguments (given #{prms.count}, expected 0)" if prms.count > 0 return self[num] end end
nth(comma=true)
click to toggle source
# File lib/nth.rb, line 1013 def nth(comma=true) Nth::IntMethods.to_nth_string(self, comma) end
pence_to_pounds()
click to toggle source
# File lib/nth.rb, line 1033 def pence_to_pounds Nth::IntMethods.pence_to_pound(self) end
respond_to_missing?(method_name, include_private = false)
click to toggle source
# File lib/nth.rb, line 1074 def respond_to_missing?(method_name, include_private = false) begin meth = method_name.to_s str = meth[-1]=="=" ? meth[0..-2] : meth num = Nth::ordinal_string_to_number(str) return num.type_of? Integer rescue return false end return false end
to_dms(sec_frac=2)
click to toggle source
# File lib/nth.rb, line 1061 def to_dms(sec_frac=2) Nth::FloatMethods.to_dms(self, sec_frac) end
to_fractional_unit(unit_name, mode = :descriptive, tar=0.01)
click to toggle source
# File lib/nth.rb, line 1046 def to_fractional_unit(unit_name, mode = :descriptive, tar=0.01) Nth::FloatMethods.to_fractional_unit(self, unit_name, mode, tar) end
to_number()
click to toggle source
# File lib/nth.rb, line 1023 def to_number Nth::IntMethods.to_number_string(self) end
to_ordinal()
click to toggle source
# File lib/nth.rb, line 1018 def to_ordinal Nth::IntMethods.to_ordinal_string(self) end