Module: Nth

Defined in:
lib/nth.rb,
lib/nth/version.rb

Defined Under Namespace

Modules: AccessMethods, FloatMethods, IntMethods

Constant Summary collapse

FRACTION_UTF =
{ "1/2" => '½', "1/4" => '¼', "3/4" => '¾', "1/3" => '', "2/3" => '',
"1/8" => '', "3/8" => '',"5/8" => '', "7/8" => '',
"1/5" => '',"2/5" => '', "3/5" => '',"4/5" => '',"1/6" => '', "5/6" => '',"1/9" => '',"1/10" => ''}
NUMBERS =
{0 => 'zero', 1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five', 6 => 'six', 7 => 'seven', 8 => 'eight', 9 => 'nine', 10 => 'ten',
11 => 'eleven', 12 => 'twelve', 13 => 'thirteen', 14 => 'fourteen', 15 => 'fifteen', 16 => 'sixteen', 17 => 'seventeen', 18 => 'eighteen', 19 => 'nineteen',  
20 => 'twenty', 30 => 'thirty', 40 => 'forty', 50 => 'fifty', 60 => 'sixty', 70 => 'seventy', 80 => 'eighty', 90 => 'ninety',   
100 => 'hundred', 
'10**3'  => 'thousand',
'10**6'  => 'million', 
'10**9'  => 'billion', 
'10**12' => 'trillion',
'10**15' => 'quadrillion', 
'10**18' => 'quintillion', 
'10**21' => 'sextillion',
'10**24' => 'septillion', 
'10**27' => 'octillion', 
'10**30' => 'nonillion',
'10**33' => 'decillion',
'10**36' => 'undecillion',
'10**39' => 'duodecillion',
'10**42' => 'tredecillion',
'10**45' => 'quattuordecillion',
'10**48' => 'quindecillion',
'10**51' => 'sexdecillion',
'10**54' => 'septendecillion',
'10**57' => 'octodecillion',
'10**60' => 'novemdecillion',   # rule generator makes this   novendecillion
'10**63' => 'vigintillion',
'10**66' => 'unvigintillion',
'10**69' => 'duovigintillion',
'10**72' => 'tresvigintillion',
'10**75' => 'quattuorvigintillion',
'10**78' => 'quinquavigintillion',
'10**81' => 'sesvigintillion',
'10**84' => 'septemvigintillion',
'10**87' => 'octovigintillion',
'10**90' => 'novemvigintillion',
'10**93' => 'trigintillion',
'10**96' => 'untrigintillion',
'10**99' => 'duotrigintillion',
'10**102' => 'trestrigintillion',       
'10**105' => 'quattuortrigintillion',   
'10**108' => 'quinquatrigintillion',
'10**111' => 'sestrigintillion',
'10**114' => 'septentrigintillion',
'10**117' => 'octotrigintillion',
'10**120' => 'noventrigintillion',
'10**123' => 'quadragintillion',
'10**100' => 'googol',
'10**3003' => 'millinillion',
'10**3006' => 'millimillion',
'10**3009' => 'millibillion',
'10**3012' => 'millitrillion',
'10**3015' => 'milliquadrillion',
'10**3018' => 'milliquintillion',
'10**3021' => 'millisextillion',
'10**3024' => 'milliseptillion',
'10**3027' => 'millioctillion',
'10**3030' => 'millinonillion',
'10**3033' => 'millidecillion',
'10**3036' => 'milliundecillion',
'10**3039' => 'milliduodecillion',
'10**3042' => 'millitredecillion',
'10**3045' => 'milliquattuordecillion',
'10**3048' => 'milliquindecillion',
'10**3051' => 'millisexdecillion',
'10**3054' => 'milliseptendecillion',
'10**3057' => 'millioctodecillion',
'10**3060' => 'millinovemdecillion',
'10**3063' => 'millivigintillion',
'10**3066' => 'milliunvigintillion',
'10**3069' => 'milliduovigintillion',
'10**3072' => 'millitresvigintillion',
'10**3075' => 'milliquattuorvigintillion',
'10**3078' => 'milliquinquavigintillion',
'10**3081' => 'millisesvigintillion',
'10**3084' => 'milliseptemvigintillion',
'10**3087' => 'millioctovigintillion',
'10**3090' => 'millinovemvigintillion',
'10**3093' => 'millitrigintillion',
'10**3096' => 'milliuntrigintillion',
'10**3099' => 'milliduotrigintillion',
'10**3102' => 'millitrestrigintillion',
'10**3105' => 'milliquattuortrigintillion',
'10**3108' => 'milliquinquatrigintillion',
'10**3111' => 'millisestrigintillion',
'10**3114' => 'milliseptentrigintillion',
'10**3117' => 'millioctotrigintillion',
'10**3120' => 'millinoventrigintillion',
'10**3123' => 'milliquadragintillion'
}
ORDINALS =

might go to just under Duomillinillion, but not until next revision to go higher, need the definitive naming scheme.

{0 => 'zeroth', 1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth', 6 => 'sixth', 7 => 'seventh', 8 => 'eighth', 9 => 'ninth', 10 => 'tenth',
11 => 'eleventh', 12 => 'twelfth', 13 => 'thirteenth', 14 => 'fourteenth', 15 => 'fifteenth', 16 => 'sixteenth', 17 => 'seventeenth', 18 => 'eighteenth', 19 => 'nineteenth',  
20 => 'twentieth', 30 => 'thirtieth', 40 => 'fortieth', 50 => 'fiftieth', 60 => 'sixtieth', 70 => 'seventieth', 80 => 'eightieth', 90 => 'ninetieth',
100 => 'hundredth', -1 => 'last'
}
ORD_FORMAT_ERROR =
"ordinal format error"
SET_TRE =

no need for extra ‘s’

[90,900,70,700,60,600,10,200]
SET_NOVE =

no need for extra ‘?’

[90,900]
PRE_TABLE =
{}
PLURAL_EXCPETIONS =
pes.freeze
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.calculate_prefix(str) ⇒ Object

Raises:



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# 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) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
# 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) ⇒ Object



688
689
690
691
692
# 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) ⇒ Object

these may need to be redone …



411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
# 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) ⇒ Object



437
438
439
440
441
# 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) ⇒ Object



584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# 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) ⇒ Object



444
445
446
447
448
449
450
451
452
453
# 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) ⇒ Object



646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
# 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) ⇒ Object



1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
# 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) ⇒ Object

this only looks up a single item… need to expand for other prefixes/



337
338
339
340
341
342
343
344
# 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) ⇒ Object



346
347
348
349
350
351
# 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) ⇒ Object



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
# 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) ⇒ Object



353
354
355
356
357
358
359
360
361
# 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) ⇒ Object



363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# 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) ⇒ Object



397
398
399
400
401
402
403
404
405
406
407
408
# 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) ⇒ Object

utility methods: the gem pluralize too simple … maybe you should fix this …

::TODO

move to new gem, then update this gem



205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# 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