ziffern 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +21 -0
  3. data/ziffern.rb +115 -0
  4. data/ziffern_spec.rb +89 -0
  5. metadata +89 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 784b7651963c3d172aa3bcf7e404760f3260eefa
4
+ data.tar.gz: 75236a977a0952a3a342bc443e66dfdad03cafac
5
+ SHA512:
6
+ metadata.gz: 074a40b8cc9ab7bc119f7c9c505c0e1709cc906f012ba6b4b79b6198bb0a6b09ca09e59acde4f755810f25b59cb896db4c78af1165be399e53991a37487dbaec
7
+ data.tar.gz: 088340abdc8033fa0175629cacf60dd3a1f4c4195ade5b290aaecc6ab414d5af89a2e719b780d367e3ef948bd29d14acec593b29bc77e108250d77d73aecd338
data/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # Ziffern
2
+
3
+ **Number to text, in _German_!**
4
+
5
+ Handles _positive and negative_ numbers up to **125 digits**, with _unlimited decimals_.
6
+
7
+ ```ruby
8
+ require 'ziffern'
9
+ converter = Ziffern.new
10
+
11
+ [1, -5, 12345, 99.99, '0.00', 10**63 + 1].each do |number|
12
+ puts converter.to_german(number)
13
+ end
14
+
15
+ # >> eins
16
+ # >> minus fünf
17
+ # >> zwölftausenddreihundertfünfundvierzig
18
+ # >> neunundneunzig Komma neun neun
19
+ # >> null Komma null null
20
+ # >> eine Dezilliarde eins
21
+ ```
data/ziffern.rb ADDED
@@ -0,0 +1,115 @@
1
+ class Ziffern
2
+
3
+ # http://de.wikipedia.org/wiki/Zahlennamen
4
+
5
+ NINETEEN = %w{ null ein zwei drei vier fünf sechs sieben acht neun zehn elf zwölf
6
+ dreizehn vierzehn fünfzehn sechzehn siebzehn achtzehn neunzehn }
7
+
8
+ TENS = %w{ zwanzig dreißig vierzig fünfzig sechzig siebzig achtzig neunzig }.unshift(nil, nil)
9
+
10
+ BIG = %w{ M B Tr Quadr Quint Sext Sept Okt Non Dez Undez Dodez Tredez
11
+ Quattuordez Quindez Sedez Septendez Dodevigint Undevigint Vigint }.flat_map do |prefix|
12
+ %W( #{prefix}illion #{prefix}illiarde )
13
+ end
14
+
15
+
16
+ def to_german(number)
17
+ convert_integer(number) + convert_decimals(number)
18
+ end
19
+
20
+ private
21
+
22
+ def convert_integer(number)
23
+ number = number.to_i
24
+ return 'eins' if number == 1
25
+ return "minus #{convert_integer(number.abs)}" if number < 0
26
+
27
+ convert(number)
28
+ end
29
+
30
+ def convert(number)
31
+ case number
32
+ when 0..19 then NINETEEN[number]
33
+ when 20..99 then twenty_to_99(number)
34
+ when 100..999 then quantify_factor(100, 'hundert', number)
35
+ when 1000..999_999 then quantify_factor(1000, 'tausend', number)
36
+ else bignums(number)
37
+ end
38
+ end
39
+
40
+ def twenty_to_99(number)
41
+ ten, remainder = number.divmod(10)
42
+
43
+ if remainder.zero?
44
+ TENS[ten]
45
+ else
46
+ "#{NINETEEN[remainder]}und#{TENS[ten]}"
47
+ end
48
+ end
49
+
50
+ def quantify_factor(factor, name, number)
51
+ amount, remainder = number.divmod(factor)
52
+
53
+ result = convert(amount) + name
54
+ result.tap do |result|
55
+ result << convert(remainder) unless remainder.zero?
56
+ end
57
+ end
58
+
59
+ def bignums(number)
60
+ number_of_millions, remainder = number.divmod(1000_000)
61
+
62
+ convert_millions(number_of_millions).tap do |result|
63
+ result << " " << convert_integer(remainder) unless remainder.zero?
64
+ end
65
+ end
66
+
67
+ def convert_millions(number_of_millions)
68
+ groups = group_with_big_names(number_of_millions)
69
+ fail ArgumentError, 'Number too large' if groups.size > BIG.size
70
+
71
+ groups
72
+ .reject { |amount, *| amount.zero? }
73
+ .map { |amount, name| quantify_big_name(amount, name) }
74
+ .join(' ')
75
+ end
76
+
77
+ def quantify_big_name(amount, big_name)
78
+ if amount == 1
79
+ quantity = 'eine'
80
+ else
81
+ quantity = convert(amount)
82
+ big_name = big_name.sub(/(e?)$/, 'en')
83
+ end
84
+
85
+ "#{quantity} #{big_name}"
86
+ end
87
+
88
+ # 12345678 => [[12, "Billion"], [345, "Milliarde"], [678, "Million"]]
89
+ def group_with_big_names(number_of_millions)
90
+ groups = []
91
+
92
+ until number_of_millions.zero?
93
+ number_of_millions, last_3 = number_of_millions.divmod(1000)
94
+ groups << last_3
95
+ end
96
+
97
+ groups.zip(BIG).reverse
98
+ end
99
+
100
+ def convert_decimals(number)
101
+ decimals = get_decimals_as_string(number)
102
+ return '' if decimals.empty?
103
+
104
+ ' Komma ' + convert_digits(decimals)
105
+ end
106
+
107
+ def get_decimals_as_string(number)
108
+ number.to_s[/\.(\d+)/, 1].to_s
109
+ end
110
+
111
+ def convert_digits(number)
112
+ number.to_s.chars.map { |digit| convert_integer(digit) }.join(' ')
113
+ end
114
+
115
+ end
data/ziffern_spec.rb ADDED
@@ -0,0 +1,89 @@
1
+ require './ziffern'
2
+
3
+ describe Ziffern do
4
+
5
+ subject { Ziffern.new }
6
+
7
+ def self.test_german_numbers(hash)
8
+ hash.each do |integer, german|
9
+ instance_eval do
10
+ it "converts #{integer} to #{german}" do
11
+ expect(subject.to_german(integer)).to eq german
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ context 'numbers up to 20' do
18
+ test_german_numbers({
19
+ 0 => "null",
20
+ 1 => "eins",
21
+ 13 => "dreizehn",
22
+ 19 => "neunzehn",
23
+ })
24
+ end
25
+
26
+ context 'numbers up to 100' do
27
+ test_german_numbers({
28
+ 20 => "zwanzig",
29
+ 21 => "einundzwanzig",
30
+ 63 => "dreiundsechzig",
31
+ 99 => "neunundneunzig",
32
+ })
33
+ end
34
+
35
+ context 'numbers up to 1000' do
36
+ test_german_numbers({
37
+ 100 => "einhundert",
38
+ 234 => "zweihundertvierunddreißig",
39
+ 999 => "neunhundertneunundneunzig",
40
+ })
41
+ end
42
+
43
+ context 'up to one million' do
44
+ test_german_numbers({
45
+ 1000 => "eintausend",
46
+ 1234 => "eintausendzweihundertvierunddreißig",
47
+ 10_000 => "zehntausend",
48
+ 999_999 => "neunhundertneunundneunzigtausendneunhundertneunundneunzig",
49
+ })
50
+ end
51
+
52
+ context 'really big numbers' do
53
+ test_german_numbers({
54
+ 1_000_000 => "eine Million",
55
+ 1_000_001 => "eine Million eins",
56
+ 2_204_510 => "zwei Millionen zweihundertviertausendfünfhundertzehn",
57
+ 1_203_400_021 => "eine Milliarde zweihundertdrei Millionen vierhunderttausendeinundzwanzig",
58
+ 3_000_000_000_000_099 => "drei Billiarden neunundneunzig",
59
+ 10 ** 123 => "eine Vigintilliarde"
60
+ })
61
+ end
62
+
63
+ it 'throws an ArgumentError if the number is bigger than it can handle' do
64
+ expect { subject.to_german(10 ** 126) }.to raise_error ArgumentError
65
+ end
66
+
67
+ context 'negative numbers' do
68
+ test_german_numbers({
69
+ -1 => "minus eins",
70
+ -20 => "minus zwanzig",
71
+ -21 => "minus einundzwanzig",
72
+ -63 => "minus dreiundsechzig",
73
+ -99 => "minus neunundneunzig",
74
+ })
75
+ end
76
+
77
+
78
+ context 'decimals' do
79
+ test_german_numbers({
80
+ 0.1234 => "null Komma eins zwei drei vier",
81
+ 5.6789 => "fünf Komma sechs sieben acht neun",
82
+ -5.6 => "minus fünf Komma sechs",
83
+ -567.89 => "minus fünfhundertsiebenundsechzig Komma acht neun",
84
+ 5.0 => "fünf Komma null",
85
+ '5.00' => "fünf Komma null null"
86
+ })
87
+ end
88
+
89
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ziffern
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jimmy Börjesson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description:
56
+ email: lagginglion@gmail.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - README.md
62
+ - ziffern.rb
63
+ - ziffern_spec.rb
64
+ homepage: https://github.com/alcesleo/ziffern
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - "."
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.2.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Converts numbers to text, in German.
88
+ test_files:
89
+ - ziffern_spec.rb