string_to_number 0.2.0 → 0.2.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94ccd123e31951522c7960a5140affb629f331e8f862e3f0336c3c15c2c86bcc
4
- data.tar.gz: b2d95e4cd38fda267ed0f73399c5af5b5e511d9f9f2baba3e14f349e6da4bf7b
3
+ metadata.gz: a97e2a69e72adda0aeedace8ab5a9ddae63c1a4741846d6d405a0ef767bdaaaa
4
+ data.tar.gz: 78553f4c606a717c8bab939e24b18ddd023a8962b902d2fea75b03498b2e3e0a
5
5
  SHA512:
6
- metadata.gz: 604ed5a2557ceb9813fee18765e0aacc33bdc6fd7a721f5d97568c65995a8e9d5609ff17eb2a44412b381a8ac10822ee602633ad9b5a0e67a984b4de0f33aba4
7
- data.tar.gz: bdff30862931f8d0d28d0c15ccf36b70056fe65c3b588c619c9452c7f92a4a732569ac4925e68af88fe67682f49854aa809b7468ee7d81005b44fd33b1c537ba
6
+ metadata.gz: 1042d45f537afc86b43883d29a3ef03ffd3ddc365a37c85843bd78fa54c4d35178c140e32c025d7406681dc31d77c06b7f7e526e4255fef1629a468a7ddf1958
7
+ data.tar.gz: 1f6b2b1e8dc6c17bf72d0ce759da2fe31dd9771188ae6087b23774b06e55f9678ee8bcc049c611ff8b0a68d9b99c8b3cb3088e28f342ae1f0d842cd618cf81da
@@ -0,0 +1,83 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ master, main ]
6
+ pull_request:
7
+ branches: [ master, main ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Ruby ${{ matrix.ruby-version }}
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby-version }}
23
+ bundler-cache: true
24
+
25
+ - name: Run tests
26
+ run: bundle exec rake spec
27
+
28
+ - name: Run performance tests
29
+ run: bundle exec rspec spec/performance_spec.rb
30
+
31
+ lint:
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Set up Ruby
37
+ uses: ruby/setup-ruby@v1
38
+ with:
39
+ ruby-version: '3.3'
40
+ bundler-cache: true
41
+
42
+ - name: Install RuboCop
43
+ run: gem install rubocop
44
+
45
+ - name: Run RuboCop
46
+ run: rubocop --format github
47
+
48
+ security:
49
+ runs-on: ubuntu-latest
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+
53
+ - name: Set up Ruby
54
+ uses: ruby/setup-ruby@v1
55
+ with:
56
+ ruby-version: '3.3'
57
+ bundler-cache: true
58
+
59
+ - name: Install bundler-audit
60
+ run: gem install bundler-audit
61
+
62
+ - name: Run bundler-audit
63
+ run: bundle audit --update
64
+
65
+ gem-build:
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+
70
+ - name: Set up Ruby
71
+ uses: ruby/setup-ruby@v1
72
+ with:
73
+ ruby-version: '3.3'
74
+ bundler-cache: true
75
+
76
+ - name: Build gem
77
+ run: gem build string_to_number.gemspec
78
+
79
+ - name: Install gem locally
80
+ run: gem install string_to_number-*.gem
81
+
82
+ - name: Test gem installation
83
+ run: ruby -e "require 'string_to_number'; puts StringToNumber.in_numbers('vingt et un')"
data/.rubocop.yml ADDED
@@ -0,0 +1,110 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.7
3
+ NewCops: enable
4
+ Exclude:
5
+ - 'vendor/**/*'
6
+ - 'pkg/**/*'
7
+ - 'tmp/**/*'
8
+ - 'bin/**/*'
9
+ - 'spec/fixtures/**/*'
10
+ SuggestExtensions: false
11
+
12
+ # Prefer double quotes for strings
13
+ Style/StringLiterals:
14
+ EnforcedStyle: single_quotes
15
+
16
+ # Allow longer lines for readability
17
+ Layout/LineLength:
18
+ Max: 120
19
+ Exclude:
20
+ - 'spec/**/*'
21
+
22
+ # Allow longer methods for complex parsing logic
23
+ Metrics/MethodLength:
24
+ Max: 25
25
+ Exclude:
26
+ - 'spec/**/*'
27
+ - 'benchmark.rb'
28
+ - 'microbenchmark.rb'
29
+ - 'performance_comparison.rb'
30
+ - 'lib/string_to_number/parser.rb'
31
+ - 'lib/string_to_number/to_number.rb'
32
+
33
+ # Allow longer classes for main implementation
34
+ Metrics/ClassLength:
35
+ Max: 250
36
+
37
+ # Allow longer blocks for test files
38
+ Metrics/BlockLength:
39
+ Max: 300
40
+ Exclude:
41
+ - 'spec/**/*'
42
+
43
+ # Allow more complex methods in parser
44
+ Metrics/CyclomaticComplexity:
45
+ Max: 12
46
+ Exclude:
47
+ - 'benchmark.rb'
48
+ - 'microbenchmark.rb'
49
+ - 'performance_comparison.rb'
50
+ - 'lib/string_to_number/parser.rb'
51
+ - 'lib/string_to_number/to_number.rb'
52
+
53
+ # Allow higher ABC size for parsing methods
54
+ Metrics/AbcSize:
55
+ Max: 20
56
+ Exclude:
57
+ - 'spec/**/*'
58
+ - 'benchmark.rb'
59
+ - 'microbenchmark.rb'
60
+ - 'performance_comparison.rb'
61
+ - 'lib/string_to_number/parser.rb'
62
+ - 'lib/string_to_number/to_number.rb'
63
+
64
+ # Allow higher perceived complexity for performance-critical methods
65
+ Metrics/PerceivedComplexity:
66
+ Max: 8
67
+ Exclude:
68
+ - 'benchmark.rb'
69
+ - 'microbenchmark.rb'
70
+ - 'performance_comparison.rb'
71
+ - 'lib/string_to_number/parser.rb'
72
+ - 'lib/string_to_number/to_number.rb'
73
+
74
+ # Allow multiple assignments for performance reasons
75
+ Style/ParallelAssignment:
76
+ Enabled: false
77
+
78
+ # Allow guard clauses without else
79
+ Style/GuardClause:
80
+ Enabled: false
81
+
82
+ # Documentation requirements
83
+ Style/Documentation:
84
+ Enabled: false
85
+
86
+ # Allow frozen string literal comments
87
+ Style/FrozenStringLiteralComment:
88
+ Enabled: true
89
+ EnforcedStyle: always
90
+
91
+
92
+ # Layout preferences
93
+ Layout/MultilineMethodCallIndentation:
94
+ EnforcedStyle: aligned
95
+
96
+ Layout/MultilineOperationIndentation:
97
+ EnforcedStyle: aligned
98
+
99
+ # Naming conventions
100
+ Naming/PredicatePrefix:
101
+ ForbiddenPrefixes:
102
+ - is_
103
+
104
+ # Allow single line methods
105
+ Style/SingleLineMethods:
106
+ AllowIfMethodIsEmpty: true
107
+
108
+ # Gem specific rules
109
+ Gemspec/RequiredRubyVersion:
110
+ Enabled: false
data/Gemfile CHANGED
@@ -1,4 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in string_to_number.gemspec
4
6
  gemspec
7
+
8
+ group :development do
9
+ gem 'bundler'
10
+ gem 'rake'
11
+ gem 'rspec'
12
+ gem 'rubocop', '~> 1.21'
13
+ end
data/Gemfile.lock CHANGED
@@ -1,13 +1,25 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- string_to_number (0.2.0)
4
+ string_to_number (0.2.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ ast (2.4.3)
9
10
  diff-lcs (1.5.0)
11
+ json (2.12.2)
12
+ language_server-protocol (3.17.0.5)
13
+ lint_roller (1.1.0)
14
+ parallel (1.27.0)
15
+ parser (3.3.8.0)
16
+ ast (~> 2.4.1)
17
+ racc
18
+ prism (1.4.0)
19
+ racc (1.8.1)
20
+ rainbow (3.1.1)
10
21
  rake (13.0.6)
22
+ regexp_parser (2.10.0)
11
23
  rspec (3.11.0)
12
24
  rspec-core (~> 3.11.0)
13
25
  rspec-expectations (~> 3.11.0)
@@ -21,6 +33,24 @@ GEM
21
33
  diff-lcs (>= 1.2.0, < 2.0)
22
34
  rspec-support (~> 3.11.0)
23
35
  rspec-support (3.11.1)
36
+ rubocop (1.77.0)
37
+ json (~> 2.3)
38
+ language_server-protocol (~> 3.17.0.2)
39
+ lint_roller (~> 1.1.0)
40
+ parallel (~> 1.10)
41
+ parser (>= 3.3.0.2)
42
+ rainbow (>= 2.2.2, < 4.0)
43
+ regexp_parser (>= 2.9.3, < 3.0)
44
+ rubocop-ast (>= 1.45.1, < 2.0)
45
+ ruby-progressbar (~> 1.7)
46
+ unicode-display_width (>= 2.4.0, < 4.0)
47
+ rubocop-ast (1.45.1)
48
+ parser (>= 3.3.7.2)
49
+ prism (~> 1.4)
50
+ ruby-progressbar (1.13.0)
51
+ unicode-display_width (3.1.4)
52
+ unicode-emoji (~> 4.0, >= 4.0.4)
53
+ unicode-emoji (4.0.4)
24
54
 
25
55
  PLATFORMS
26
56
  x86_64-linux
@@ -29,6 +59,7 @@ DEPENDENCIES
29
59
  bundler
30
60
  rake
31
61
  rspec
62
+ rubocop (~> 1.21)
32
63
  string_to_number!
33
64
 
34
65
  BUNDLED WITH
data/README.md CHANGED
@@ -1,8 +1,12 @@
1
- # StringToNumber
2
-
3
- [![Gem Version](https://badge.fury.io/rb/string_to_number.svg)](https://badge.fury.io/rb/string_to_number)
4
- [![Ruby](https://github.com/FabienPiette/string_to_number/workflows/Ruby/badge.svg)](https://github.com/FabienPiette/string_to_number/actions)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
1
+ <div align="center">
2
+ <img src="logo.png" alt="StringToNumber Logo" width="200" height="200">
3
+
4
+ # StringToNumber
5
+
6
+ [![Gem Version](https://badge.fury.io/rb/string_to_number.svg)](https://badge.fury.io/rb/string_to_number)
7
+ [![Ruby](https://github.com/FabienPiette/string_to_number/workflows/Ruby/badge.svg)](https://github.com/FabienPiette/string_to_number/actions)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+ </div>
6
10
 
7
11
  A high-performance Ruby gem for converting French written numbers into their numeric equivalents. Features intelligent caching, thread-safe operations, and support for complex French number formats.
8
12
 
data/Rakefile CHANGED
@@ -1,9 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
3
6
 
4
7
  RSpec::Core::RakeTask.new(:spec)
8
+ RuboCop::RakeTask.new
5
9
 
6
- task default: :spec
10
+ task default: %i[rubocop spec]
7
11
 
8
12
  task :env, [:env] do |_t, _args|
9
13
  require 'string_to_number'
data/benchmark.rb CHANGED
@@ -10,8 +10,8 @@ require 'benchmark'
10
10
  class StringToNumberBenchmark
11
11
  # Test data organized by complexity
12
12
  TEST_CASES = {
13
- simple: [
14
- 'un', 'vingt', 'cent', 'mille'
13
+ simple: %w[
14
+ un vingt cent mille
15
15
  ],
16
16
  medium: [
17
17
  'vingt et un', 'deux cent cinquante', 'mille deux cent'
@@ -20,20 +20,20 @@ class StringToNumberBenchmark
20
20
  'trois milliards cinq cents millions',
21
21
  'soixante-quinze million trois cent quarante six mille sept cent quatre-vingt-dix neuf'
22
22
  ],
23
- edge_cases: [
24
- 'VINGT', 'une', 'septante', 'quatre-vingts'
23
+ edge_cases: %w[
24
+ VINGT une septante quatre-vingts
25
25
  ]
26
26
  }.freeze
27
27
 
28
28
  def self.run_benchmark
29
- puts "StringToNumber Performance Benchmark"
30
- puts "=" * 50
29
+ puts 'StringToNumber Performance Benchmark'
30
+ puts '=' * 50
31
31
  puts "Ruby version: #{RUBY_VERSION}"
32
32
  puts "Platform: #{RUBY_PLATFORM}"
33
33
  puts
34
34
 
35
35
  # Warm up
36
- puts "Warming up..."
36
+ puts 'Warming up...'
37
37
  TEST_CASES.values.flatten.each { |text| StringToNumber.in_numbers(text) }
38
38
  puts
39
39
 
@@ -41,7 +41,7 @@ class StringToNumberBenchmark
41
41
 
42
42
  TEST_CASES.each do |category, test_cases|
43
43
  puts "#{category.to_s.capitalize} Numbers:"
44
- puts "-" * 30
44
+ puts '-' * 30
45
45
 
46
46
  results = benchmark_category(test_cases)
47
47
  total_results[category] = results
@@ -53,46 +53,44 @@ class StringToNumberBenchmark
53
53
  puts
54
54
 
55
55
  # Show individual case performance for complex numbers
56
- if category == :complex
57
- puts "Individual case breakdown:"
58
- test_cases.each_with_index do |text, index|
59
- individual_time = Benchmark.realtime do
60
- 1000.times { StringToNumber.in_numbers(text) }
61
- end
62
- avg_ms = (individual_time / 1000) * 1000
63
- puts " #{index + 1}. #{avg_ms.round(4)}ms - '#{text[0..50]}#{text.length > 50 ? '...' : ''}'"
56
+ next unless category == :complex
57
+
58
+ puts 'Individual case breakdown:'
59
+ test_cases.each_with_index do |text, index|
60
+ individual_time = Benchmark.realtime do
61
+ 1000.times { StringToNumber.in_numbers(text) }
64
62
  end
65
- puts
63
+ avg_ms = (individual_time / 1000) * 1000
64
+ puts " #{index + 1}. #{avg_ms.round(4)}ms - '#{text[0..50]}#{'...' if text.length > 50}'"
66
65
  end
66
+ puts
67
67
  end
68
68
 
69
69
  # Summary
70
- puts "=" * 50
71
- puts "PERFORMANCE SUMMARY"
72
- puts "=" * 50
70
+ puts '=' * 50
71
+ puts 'PERFORMANCE SUMMARY'
72
+ puts '=' * 50
73
73
 
74
74
  total_results.each do |category, results|
75
75
  status = case results[:avg_time_ms]
76
- when 0..0.1 then "🟢 Excellent"
77
- when 0.1..0.5 then "🟡 Good"
78
- when 0.5..1.0 then "🟠 Acceptable"
79
- else "🔴 Needs optimization"
76
+ when 0..0.1 then '🟢 Excellent'
77
+ when 0.1..0.5 then '🟡 Good'
78
+ when 0.5..1.0 then '🟠 Acceptable'
79
+ else '🔴 Needs optimization'
80
80
  end
81
-
81
+
82
82
  puts "#{category.to_s.capitalize.ljust(12)} #{status.ljust(15)} #{results[:avg_time_ms].round(4)}ms avg"
83
83
  end
84
84
 
85
85
  puts
86
- puts "Memory efficiency test..."
86
+ puts 'Memory efficiency test...'
87
87
  test_memory_usage
88
88
 
89
89
  puts
90
- puts "Scalability test..."
90
+ puts 'Scalability test...'
91
91
  test_scalability
92
92
  end
93
93
 
94
- private
95
-
96
94
  def self.benchmark_category(test_cases, iterations = 2000)
97
95
  total_time = Benchmark.realtime do
98
96
  test_cases.each do |text|
@@ -130,7 +128,7 @@ class StringToNumberBenchmark
130
128
 
131
129
  puts "Object creation: #{object_growth} new objects (#{object_growth > 1000 ? '🔴 High' : '🟢 Low'})"
132
130
  else
133
- puts "Memory tracking not available on this platform"
131
+ puts 'Memory tracking not available on this platform'
134
132
  end
135
133
  end
136
134
 
@@ -138,27 +136,32 @@ class StringToNumberBenchmark
138
136
  # Test how performance scales with input complexity
139
137
  inputs = [
140
138
  'un', # 2 chars
141
- 'vingt et un', # 11 chars
139
+ 'vingt et un', # 11 chars
142
140
  'mille deux cent trente-quatre', # 29 chars
143
141
  'trois milliards cinq cents millions deux cent mille et une' # 58 chars
144
142
  ]
145
143
 
146
- puts "Input length vs. performance:"
147
-
144
+ puts 'Input length vs. performance:'
145
+
148
146
  results = inputs.map do |input|
149
147
  time = Benchmark.realtime do
150
148
  1000.times { StringToNumber.in_numbers(input) }
151
149
  end
152
150
  avg_ms = (time / 1000) * 1000
153
-
151
+
154
152
  { length: input.length, time: avg_ms, input: input }
155
153
  end
156
154
 
157
155
  results.each do |result|
158
156
  complexity_ratio = result[:time] / results.first[:time]
159
- status = complexity_ratio < 5 ? "🟢" : complexity_ratio < 10 ? "🟡" : "🔴"
160
-
161
- puts " #{result[:length].to_s.rjust(2)} chars: #{result[:time].round(4)}ms #{status} (#{complexity_ratio.round(1)}x baseline)"
157
+ status = if complexity_ratio < 5
158
+ '🟢'
159
+ else
160
+ complexity_ratio < 10 ? '🟡' : '🔴'
161
+ end
162
+
163
+ puts " #{result[:length].to_s.rjust(2)} chars: #{result[:time].round(4)}ms #{status} " \
164
+ "(#{complexity_ratio.round(1)}x baseline)"
162
165
  end
163
166
 
164
167
  # Check if performance degrades reasonably
@@ -172,6 +175,4 @@ class StringToNumberBenchmark
172
175
  end
173
176
 
174
177
  # Run the benchmark
175
- if __FILE__ == $0
176
- StringToNumberBenchmark.run_benchmark
177
- end
178
+ StringToNumberBenchmark.run_benchmark if __FILE__ == $PROGRAM_NAME
@@ -2,7 +2,7 @@
2
2
 
3
3
  module StringToNumber
4
4
  # High-performance French text to number parser
5
- #
5
+ #
6
6
  # This class provides a clean, optimized implementation that maintains
7
7
  # compatibility with the original algorithm while adding significant
8
8
  # performance improvements through caching and memoization.
@@ -23,9 +23,9 @@ module StringToNumber
23
23
  # Pre-compiled regex patterns for optimal performance
24
24
  MULTIPLIER_KEYS = MULTIPLIERS.keys.reject { |k| %w[un dix].include?(k) }
25
25
  .sort_by(&:length).reverse.freeze
26
- MULTIPLIER_PATTERN = /(?<f>.*?)\s?(?<m>#{MULTIPLIER_KEYS.join('|')})/
27
- QUATRE_VINGT_PATTERN = /(quatre(-|\s)vingt(s?)((-|\s)dix)?)((-|\s)?)(\w*)/
28
-
26
+ MULTIPLIER_PATTERN = /(?<f>.*?)\s?(?<m>#{MULTIPLIER_KEYS.join('|')})/.freeze
27
+ QUATRE_VINGT_PATTERN = /(quatre(-|\s)vingt(s?)((-|\s)dix)?)((-|\s)?)(\w*)/.freeze
28
+
29
29
  # Cache configuration
30
30
  MAX_CACHE_SIZE = 1000
31
31
  private_constant :MAX_CACHE_SIZE
@@ -45,7 +45,7 @@ module StringToNumber
45
45
  # @raise [ArgumentError] if text is not a string
46
46
  def convert(text)
47
47
  validate_input!(text)
48
-
48
+
49
49
  normalized = normalize_text(text)
50
50
  return 0 if normalized.empty?
51
51
 
@@ -56,7 +56,7 @@ module StringToNumber
56
56
  # Get or create parser instance and convert
57
57
  parser = get_cached_instance(normalized)
58
58
  result = parser.parse_optimized(normalized)
59
-
59
+
60
60
  # Cache the result
61
61
  cache_conversion(normalized, result)
62
62
  result
@@ -68,7 +68,7 @@ module StringToNumber
68
68
  @conversion_cache.clear
69
69
  @cache_access_order.clear
70
70
  end
71
-
71
+
72
72
  @instance_mutex.synchronize do
73
73
  @instance_cache.clear
74
74
  end
@@ -115,7 +115,7 @@ module StringToNumber
115
115
  oldest = @cache_access_order.shift
116
116
  @conversion_cache.delete(oldest)
117
117
  end
118
-
118
+
119
119
  @conversion_cache[normalized_text] = result
120
120
  @cache_access_order.push(normalized_text)
121
121
  end
@@ -129,6 +129,7 @@ module StringToNumber
129
129
 
130
130
  def calculate_hit_ratio
131
131
  return 0.0 if @cache_access_order.empty?
132
+
132
133
  @conversion_cache.size.to_f / @cache_access_order.size
133
134
  end
134
135
  end
@@ -147,7 +148,7 @@ module StringToNumber
147
148
  # but with performance optimizations
148
149
  def parse_optimized(text)
149
150
  return 0 if text.nil? || text.empty?
150
-
151
+
151
152
  # Direct lookup (fastest path)
152
153
  return WORD_VALUES[text] if WORD_VALUES.key?(text)
153
154
 
@@ -162,12 +163,12 @@ module StringToNumber
162
163
  # but with performance improvements
163
164
  def extract_optimized(sentence, keys, detail: false)
164
165
  return 0 if sentence.nil? || sentence.empty?
165
-
166
+
166
167
  # Direct lookup
167
168
  return WORD_VALUES[sentence] if WORD_VALUES.key?(sentence)
168
169
 
169
170
  # Main pattern matching using pre-compiled regex
170
- if result = MULTIPLIER_PATTERN.match(sentence)
171
+ if (result = MULTIPLIER_PATTERN.match(sentence))
171
172
  # Remove matched portion
172
173
  sentence = sentence.gsub(result[0], '') if result[0]
173
174
 
@@ -193,19 +194,19 @@ module StringToNumber
193
194
  }
194
195
  end
195
196
 
196
- return extract_optimized(sentence, keys) + factor * multiple_of_ten
197
+ extract_optimized(sentence, keys) + (factor * multiple_of_ten)
197
198
 
198
199
  # Quatre-vingt special handling
199
- elsif m = QUATRE_VINGT_PATTERN.match(sentence)
200
+ elsif (m = QUATRE_VINGT_PATTERN.match(sentence))
200
201
  normalize_str = m[1].tr(' ', '-')
201
202
  normalize_str = normalize_str[0...-1] if normalize_str[-1] == 's'
202
203
 
203
204
  sentence = sentence.gsub(m[0], '')
204
205
 
205
- return extract_optimized(sentence, keys) +
206
- WORD_VALUES[normalize_str] + (WORD_VALUES[m[8]] || 0)
206
+ extract_optimized(sentence, keys) +
207
+ WORD_VALUES[normalize_str] + (WORD_VALUES[m[8]] || 0)
207
208
  else
208
- return match_optimized(sentence)
209
+ match_optimized(sentence)
209
210
  end
210
211
  end
211
212
 
@@ -213,8 +214,9 @@ module StringToNumber
213
214
  def match_optimized(sentence)
214
215
  return 0 if sentence.nil?
215
216
 
216
- sentence.tr('-', ' ').split(' ').reverse.sum do |word|
217
+ sentence.tr('-', ' ').split.reverse.sum do |word|
217
218
  next 0 if word == 'et'
219
+
218
220
  WORD_VALUES[word] || (MULTIPLIERS[word] ? 10 * MULTIPLIERS[word] : 0)
219
221
  end
220
222
  end
@@ -227,4 +229,4 @@ module StringToNumber
227
229
  end
228
230
  end
229
231
  end
230
- end
232
+ end