numbers_in_words 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.1.7"
5
+ - "2.2.3"
6
+ - rbx
7
+ script: ./bin/spec
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem "codeclimate-test-reporter", group: :test, require: nil
3
4
  # Specify your gem's dependencies in numbers_in_words.gemspec
4
5
  gemspec
data/README.md CHANGED
@@ -1,7 +1,14 @@
1
+ [![Build Status](http://img.shields.io/travis/markburns/numbers_in_words.svg)](https://travis-ci.org/markburns/numbers_in_words)
2
+ [![Dependency Status](http://img.shields.io/gemnasium/markburns/numbers_in_words.svg)](https://gemnasium.com/markburns/numbers_in_words)
3
+ [![Code Climate](http://img.shields.io/codeclimate/github/markburns/numbers_in_words.svg)](https://codeclimate.com/github/markburns/numbers_in_words)
4
+ [![Gem Version](http://img.shields.io/gem/v/numbers_in_words.svg)](https://rubygems.org/gems/numbers_in_words)
5
+ [![License](http://img.shields.io/:license-mit-blue.svg)](http://markburns.mit-license.org)
6
+ [![Badges](http://img.shields.io/:badges-6/6-ff6799.svg)](https://github.com/badges/badgerbadgerbadger)
7
+
1
8
  Installation
2
9
  ============
3
10
 
4
- ```
11
+ ```ruby
5
12
  gem 'numbers_in_words'
6
13
 
7
14
  require 'numbers_in_words'
@@ -11,32 +18,24 @@ require 'numbers_in_words/duck_punch' #see why later
11
18
  This project was created for a test for a job interview. I haven't really used
12
19
  it myself, but I saw it mentioned somewhere so I thought I'd tidy it up a bit.
13
20
 
14
- I'm going to hopefully preempt some support queries by predicting this will happen:
15
-
16
- You've got one of:
21
+ Usage
22
+ =========
17
23
 
18
- ```
19
- NoMethodError: undefined method `in_words' for 123:Fixnum
20
- NoMethodError: undefined method `in_numbers' for "123":String
21
- ```
24
+ ```ruby
25
+ require 'numbers_in_words'
22
26
 
23
- Here's why
24
- ==========
27
+ NumbersInWords.in_words(112)
28
+ #=> one hundred and twelve
25
29
 
26
- Previous versions of this gem duckpunched Fixnum and String with a whole bunch
27
- of methods. This gem will now only add methods if you specifically tell it to
28
- with:
30
+ NumbersInWords.in_numbers(112)
31
+ #=>10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
29
32
 
30
- ```
31
- require 'numbers_in_words'
32
- require 'numbers_in_words/duck_punch'
33
+ NumbersInWords.in_numbers("Seventy million, five-hundred and fifty six thousand point eight nine three")
34
+ #=> 70556000.893
33
35
  ```
34
36
 
35
- Plus it now only adds a single `#in_words` method to `Numeric` and an `#in_numbers`
36
- method to `String` instead of a whole bunch of them.
37
37
 
38
- Usage
39
- =========
38
+ Monkey patch version
40
39
 
41
40
  ```ruby
42
41
  require 'numbers_in_words'
@@ -51,42 +50,30 @@ require 'numbers_in_words/duck_punch'
51
50
  #=> 70556000.893
52
51
  ```
53
52
 
54
- ---------------
55
-
56
- Whilst creating this project I realized that in English:
57
-
58
- * Numbers are grouped in groups of threes
59
- * Numbers less than 1,000 are grouped by hundreds and then by tens
60
- * There are specific rules for when we put an "and" in between numbers
61
53
 
62
- It makes sense to manage the numbers by these groups, so
63
- I created a method groups_of which will split any integer into
64
- groups of a certain size. It returns a hash with the power of ten
65
- as the key and the multiplier as the value. E.g:
54
+ NoMethodError `in_words` or `in_numbers`
55
+ ----------
56
+ I'm going to hopefully preempt some support queries by predicting this will happen:
66
57
 
67
- ```ruby
68
- 31245.groups_of(3)
69
- #=> {0=>245,3=>31} #i.e. 31 thousands, and 245 ones
58
+ You've got one of:
70
59
 
71
- 245.group_of(2)
72
- #=> {0=>45,2=>2} #i.e. 2 hundreds, and 45 ones
60
+ ```
61
+ NoMethodError: undefined method `in_words' for 123:Fixnum
62
+ NoMethodError: undefined method `in_numbers' for "123":String
73
63
  ```
74
64
 
75
- (In Japanese numbers are grouped in groups of 4, so it makes sense to try and
76
- separate the language related stuff from the number grouping related stuff)
77
-
78
- Example of usage:
65
+ Previous versions of this gem duckpunched Fixnum and String with a whole bunch
66
+ of methods. This gem will now only add methods if you specifically tell it to
67
+ with:
79
68
 
80
69
  ```ruby
81
- 245.group_words(2,"English") do |power, name, digits|
82
- puts "#{digits}*10^#{power} #{digits} #{name}s"
83
- end
84
-
70
+ require 'numbers_in_words'
71
+ require 'numbers_in_words/duck_punch'
72
+ ```
85
73
 
86
- 2 * 10^2 = 2 hundreds
87
- 45 * 10^0 = 45 ones
74
+ Plus it now only adds a single `#in_words` method to `Numeric` and an `#in_numbers`
75
+ method to `String` instead of a whole bunch of them.
88
76
 
89
- ```
90
77
 
91
78
  Future plans
92
79
  ============
data/bin/spec ADDED
@@ -0,0 +1,2 @@
1
+ bundle exec rspec spec/non_monkey_patch_spec.rb
2
+ bundle exec rspec spec
@@ -16,9 +16,18 @@ module NumbersInWords
16
16
 
17
17
  class << self
18
18
  attr_writer :language
19
+
19
20
  def language
20
21
  @language ||= "English"
21
22
  end
23
+
24
+ def in_words(i, language=NumbersInWords.language)
25
+ NumbersInWords::ToWord.new(i, language).in_words
26
+ end
27
+
28
+ def in_numbers(s, language=NumbersInWords.language)
29
+ NumbersInWords::ToNumber.new(s, language).in_numbers
30
+ end
22
31
  end
23
32
  end
24
33
 
@@ -1,12 +1,12 @@
1
1
  module NumbersInWords
2
2
  def in_words language=NumbersInWords.language
3
- NumbersInWords::ToWord.new(self, language).in_words
3
+ NumbersInWords.in_words(self, language)
4
4
  end
5
5
  end
6
6
 
7
7
  module WordsInNumbers
8
8
  def in_numbers language=NumbersInWords.language
9
- NumbersInWords::ToNumber.new(self, language).in_numbers
9
+ NumbersInWords.in_numbers(self, language)
10
10
  end
11
11
  end
12
12
 
@@ -9,7 +9,7 @@ module NumbersInWords
9
9
  end
10
10
 
11
11
  def negative
12
- "minus " + (-@that).in_words
12
+ "minus " + NumbersInWords.in_words(-@that)
13
13
  end
14
14
 
15
15
  def in_words
@@ -33,13 +33,12 @@ module NumbersInWords
33
33
 
34
34
  digit = number - tens #write the digits
35
35
 
36
- output << " " + digit.in_words unless digit==0
36
+ output << " " + NumbersInWords.in_words(digit) unless digit==0
37
37
  else
38
38
  output << write() #longer numbers
39
39
  end
40
40
 
41
41
  output.strip
42
-
43
42
  end
44
43
 
45
44
  def handle_exception
@@ -67,24 +66,27 @@ module NumbersInWords
67
66
  def decimals
68
67
  int, decimals = NumberGroup.new(@that).split_decimals
69
68
  if int
70
- out = int.in_words + " point "
69
+ out = NumbersInWords.in_words(int) + " point "
71
70
  decimals.each do |decimal|
72
- out << decimal.to_i.in_words + " "
71
+ out << NumbersInWords.in_words(decimal.to_i) + " "
73
72
  end
74
73
  out.strip
75
74
  end
76
75
  end
77
76
 
78
77
  private
78
+
79
79
  def write_googols
80
80
  googols, remainder = NumberGroup.new(@that).split_googols
81
81
  output = ""
82
- output << " " + googols.in_words + " googol"
82
+
83
+ output << " " + NumbersInWords.in_words(googols) + " googol"
83
84
  if remainder > 0
84
85
  prefix = " "
85
86
  prefix << "and " if remainder < 100
86
- output << prefix + remainder.in_words
87
+ output << prefix + NumbersInWords.in_words(remainder)
87
88
  end
89
+
88
90
  output
89
91
  end
90
92
 
@@ -96,7 +98,7 @@ module NumbersInWords
96
98
  prefix = " "
97
99
  #no and between thousands and hundreds
98
100
  prefix << "and " if power == 0 and digits < 100
99
- output << prefix + digits.in_words
101
+ output << prefix + NumbersInWords.in_words(digits)
100
102
  output << prefix + name unless power == 0
101
103
  end
102
104
  end
@@ -43,7 +43,7 @@ module NumbersInWords::NumberParser
43
43
  memory = 0
44
44
  answer = 0
45
45
  reset = true #reset each time memory is reset
46
- integers.each_with_index do |integer, index|
46
+ integers.each do |integer|
47
47
  if reset
48
48
  reset = false
49
49
  memory += integer
@@ -1,3 +1,3 @@
1
1
  module NumbersInWords
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -14,8 +14,7 @@ Gem::Specification.new do |gem|
14
14
  gem.homepage = "http://github.com/markburns/numbers_in_words"
15
15
 
16
16
  gem.add_dependency "activesupport"
17
- gem.add_development_dependency "rspec"
18
- gem.add_development_dependency "debugger"
17
+ gem.add_development_dependency "rspec", "~> 3.4.0"
19
18
 
20
19
  gem.files = `git ls-files`.split($/)
21
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -7,13 +7,13 @@ describe NumbersInWords::English::LanguageWriterEnglish do
7
7
  @writer.group_words(3) do |power, name, digits|
8
8
  case count
9
9
  when 0
10
- power.should == 3
11
- name.should == "thousand"
12
- digits.should == 2
10
+ expect(power).to eq(3)
11
+ expect(name).to eq("thousand")
12
+ expect(digits).to eq(2)
13
13
  when 1
14
- power.should == 0
15
- name.should == "one"
16
- digits.should == 111
14
+ expect(power).to eq(0)
15
+ expect(name).to eq("one")
16
+ expect(digits).to eq(111)
17
17
  end
18
18
  count += 1
19
19
  end
@@ -0,0 +1,26 @@
1
+ require 'numbers_in_words'
2
+
3
+ describe "NumbersInWords" do
4
+ describe ".in_words" do
5
+ it do
6
+ expect(NumbersInWords.in_words(100)).to eq "one hundred"
7
+ expect(NumbersInWords.in_words(-100)).to eq "minus one hundred"
8
+ expect(NumbersInWords.in_words(24)).to eq "twenty four"
9
+ expect(NumbersInWords.in_words(1.2)).to eq "one point two"
10
+ expect(NumbersInWords.in_words(100*10**100)).to eq "one hundred googol"
11
+ expect(NumbersInWords.in_words(30 + 100*10**100)).to eq "one hundred googol and thirty"
12
+ end
13
+
14
+ pending "This should be implemented" do
15
+ expect(NumbersInWords.in_words(100*10**100)).to eq "one hundred googols"
16
+ end
17
+ end
18
+
19
+ describe ".in_numbers" do
20
+ it do
21
+ expect(NumbersInWords.in_numbers("one hundred")).to eq 100
22
+ end
23
+ end
24
+
25
+
26
+ end
@@ -4,13 +4,13 @@ describe NumbersInWords::NumberGroup do
4
4
  it "should split into group of three digit numbers" do
5
5
  g = Numeric::NumberGroup
6
6
 
7
- g.groups_of(1 ,3 ).should == {0=>1 }
8
- g.groups_of(12 ,3 ).should == {0=>12 }
9
- g.groups_of(123 ,3 ).should == {0=>123 }
10
- g.groups_of(1111 ,3 ).should == {3=>1 , 0=>111 }
11
- g.groups_of(87654 ,3 ).should == {3=>87 , 0=>654 }
12
- g.groups_of(1_234_567 ,3 ).should == {6=>1 , 3=>234 , 0=>567 }
13
- g.groups_of(123_456_789_101_112 ,3 ).should == {12=>123 , 9=>456 , 6=>789 , 3=>101 , 0=>112 }
7
+ expect(g.groups_of(1 ,3 )).to eq({0=>1 })
8
+ expect(g.groups_of(12 ,3 )).to eq({0=>12 })
9
+ expect(g.groups_of(123 ,3 )).to eq({0=>123 })
10
+ expect(g.groups_of(1111 ,3 )).to eq({3=>1 , 0=>111 })
11
+ expect(g.groups_of(87654 ,3 )).to eq({3=>87 , 0=>654 })
12
+ expect(g.groups_of(1_234_567 ,3 )).to eq({6=>1 , 3=>234 , 0=>567 })
13
+ expect(g.groups_of(123_456_789_101_112 ,3 )).to eq({12=>123 , 9=>456 , 6=>789 , 3=>101 , 0=>112 })
14
14
  end
15
15
  end
16
16
 
@@ -1,79 +1,106 @@
1
1
  require './spec/spec_helper'
2
2
 
3
3
  describe NumbersInWords do
4
+ describe ".language" do
5
+ after do
6
+ NumbersInWords.instance_variable_set(:"@language", nil)
7
+ end
8
+
9
+ it "has a default value" do
10
+ expect(NumbersInWords.language).to eq "English"
11
+ end
12
+
13
+ it "can be set" do
14
+ NumbersInWords.language = "some language"
15
+ expect(NumbersInWords.language).to eq "some language"
16
+ end
17
+ end
18
+
19
+ describe ".in_words" do
20
+ it do
21
+ expect(NumbersInWords.in_words(100)).to eq "one hundred"
22
+ end
23
+ end
24
+
25
+ describe ".in_numbers" do
26
+ it do
27
+ expect(NumbersInWords.in_numbers("one hundred")).to eq 100
28
+ end
29
+ end
30
+
4
31
  it "should print the digits 0-9 correctly" do
5
32
  numbers = %w[zero one two three four five six seven eight nine]
6
33
 
7
- 10.times { |i| i.in_words.should==numbers[i] }
34
+ 10.times { |i| expect(i.in_words).to eq(numbers[i]) }
8
35
  end
9
36
 
10
37
  it "should print the digits 11-19 correctly" do
11
38
  words = %w[eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen]
12
39
  numbers = [11,12,13,14,15,16,17,18,19]
13
40
  numbers.each_with_index do |number, index|
14
- number.in_words.should==words[index]
41
+ expect(number.in_words).to eq(words[index])
15
42
 
16
43
  end
17
44
  end
18
45
 
19
46
  it "should handle two digit numbers" do
20
- 21.in_words. should == "twenty one"
47
+ expect(21.in_words). to eq("twenty one")
21
48
  end
22
49
 
23
50
  it "should handle three digit numbers" do
24
- 113.in_words. should == "one hundred and thirteen"
25
- 299.in_words. should == "two hundred and ninety nine"
26
- 300.in_words. should == "three hundred"
27
- 101.in_words. should == "one hundred and one"
51
+ expect(113.in_words). to eq("one hundred and thirteen")
52
+ expect(299.in_words). to eq("two hundred and ninety nine")
53
+ expect(300.in_words). to eq("three hundred")
54
+ expect(101.in_words). to eq("one hundred and one")
28
55
  end
29
56
 
30
57
  it "should print out some random examples correctly" do
31
- 2999 .in_words. should == "two thousand nine hundred and ninety nine"
32
- 99999 .in_words. should == "ninety nine thousand nine hundred and ninety nine"
33
- 999999 .in_words. should == "nine hundred and ninety nine thousand nine hundred and ninety nine"
34
- 123456 .in_words. should == "one hundred and twenty three thousand four hundred and fifty six"
35
- 17054 .in_words. should == "seventeen thousand and fifty four"
36
- 11004 .in_words. should == "eleven thousand and four"
37
- 470154 .in_words. should == "four hundred and seventy thousand one hundred and fifty four"
38
- 417155 .in_words. should == "four hundred and seventeen thousand one hundred and fifty five"
39
- 999999 .in_words. should == "nine hundred and ninety nine thousand nine hundred and ninety nine"
40
- 1000000 .in_words. should == "one million"
41
- 1000001 .in_words. should == "one million and one"
42
- 112 .in_words. should == "one hundred and twelve"
58
+ expect(2999 .in_words). to eq("two thousand nine hundred and ninety nine")
59
+ expect(99999 .in_words). to eq("ninety nine thousand nine hundred and ninety nine")
60
+ expect(999999 .in_words). to eq("nine hundred and ninety nine thousand nine hundred and ninety nine")
61
+ expect(123456 .in_words). to eq("one hundred and twenty three thousand four hundred and fifty six")
62
+ expect(17054 .in_words). to eq("seventeen thousand and fifty four")
63
+ expect(11004 .in_words). to eq("eleven thousand and four")
64
+ expect(470154 .in_words). to eq("four hundred and seventy thousand one hundred and fifty four")
65
+ expect(417155 .in_words). to eq("four hundred and seventeen thousand one hundred and fifty five")
66
+ expect(999999 .in_words). to eq("nine hundred and ninety nine thousand nine hundred and ninety nine")
67
+ expect(1000000 .in_words). to eq("one million")
68
+ expect(1000001 .in_words). to eq("one million and one")
69
+ expect(112 .in_words). to eq("one hundred and twelve")
43
70
  end
44
71
 
45
72
  it "should handle edge cases" do
46
- 1000001 .in_words. should == "one million and one"
47
- (10*10**12 + 10**6 +1) .in_words. should == "ten trillion one million and one"
48
- (10**75) .in_words. should == "one quattuorvigintillion"
49
- 10001001 .in_words. should == "ten million one thousand and one"
73
+ expect(1000001 .in_words). to eq("one million and one")
74
+ expect((10*10**12 + 10**6 +1) .in_words). to eq("ten trillion one million and one")
75
+ expect((10**75) .in_words). to eq("one quattuorvigintillion")
76
+ expect(10001001 .in_words). to eq("ten million one thousand and one")
50
77
  end
51
78
 
52
79
  it "should handle a googol and larger" do
53
80
  n=10**100
54
- (10**100 + 1) .in_words. should == "one googol and one"
55
- (42*10**100 + 16777216).in_words. should == "forty two googol sixteen million seven hundred and seventy seven thousand two hundred and sixteen"
56
- (42* 10**100 * 10**100).in_words. should == "forty two googol googol"
81
+ expect((10**100 + 1) .in_words). to eq("one googol and one")
82
+ expect((42*10**100 + 16777216).in_words). to eq("forty two googol sixteen million seven hundred and seventy seven thousand two hundred and sixteen")
83
+ expect((42* 10**100 * 10**100).in_words). to eq("forty two googol googol")
57
84
  end
58
85
 
59
86
  it "should handle negative numbers" do
60
- -1 .in_words.should == "minus one"
61
- -9 .in_words.should == "minus nine"
62
- -10 .in_words.should == "minus ten"
63
- -15 .in_words.should == "minus fifteen"
64
- -100 .in_words.should == "minus one hundred"
65
- (-1*(10**100)).in_words.should == "minus one googol"
66
- -123456789 .in_words.should == "minus one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine"
87
+ expect(-1 .in_words).to eq("minus one")
88
+ expect(-9 .in_words).to eq("minus nine")
89
+ expect(-10 .in_words).to eq("minus ten")
90
+ expect(-15 .in_words).to eq("minus fifteen")
91
+ expect(-100 .in_words).to eq("minus one hundred")
92
+ expect((-1*(10**100)).in_words).to eq("minus one googol")
93
+ expect(-123456789 .in_words).to eq("minus one hundred and twenty three million four hundred and fifty six thousand seven hundred and eighty nine")
67
94
  end
68
95
 
69
96
  it "should handle decimals" do
70
97
  #because of lack of absolute accuracy with floats
71
98
  #the output won't be exactly as you might expect
72
99
  #so we will match rather than find equivalents
73
- 1.1 .in_words.should =~ /one point one/
74
- 1.2345678 .in_words.should =~ /one point two three four five six seven eight/
75
- 1000.2345678 .in_words.should =~ /one thousand point two three four five six seven eight/
76
- 12345.2345678.in_words.should =~ /twelve thousand three hundred and forty five point two three four five six seven eight/
77
- (10**9 + 0.1).in_words.should =~ /one billion point one/
100
+ expect(1.1 .in_words).to match(/one point one/)
101
+ expect(1.2345678 .in_words).to match(/one point two three four five six seven eight/)
102
+ expect(1000.2345678 .in_words).to match(/one thousand point two three four five six seven eight/)
103
+ expect(12345.2345678.in_words).to match(/twelve thousand three hundred and forty five point two three four five six seven eight/)
104
+ expect((10**9 + 0.1).in_words).to match(/one billion point one/)
78
105
  end
79
106
  end