string_to_number 0.1.4 → 0.2.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.
- checksums.yaml +4 -4
- data/.tool-versions +1 -0
- data/CLAUDE.md +103 -0
- data/Gemfile.lock +2 -2
- data/README.md +177 -22
- data/benchmark.rb +177 -0
- data/lib/string_to_number/parser.rb +230 -0
- data/lib/string_to_number/to_number.rb +137 -30
- data/lib/string_to_number/version.rb +1 -1
- data/lib/string_to_number.rb +90 -3
- data/microbenchmark.rb +226 -0
- data/performance_comparison.rb +155 -0
- data/profile.rb +131 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94ccd123e31951522c7960a5140affb629f331e8f862e3f0336c3c15c2c86bcc
|
4
|
+
data.tar.gz: b2d95e4cd38fda267ed0f73399c5af5b5e511d9f9f2baba3e14f349e6da4bf7b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 604ed5a2557ceb9813fee18765e0aacc33bdc6fd7a721f5d97568c65995a8e9d5609ff17eb2a44412b381a8ac10822ee602633ad9b5a0e67a984b4de0f33aba4
|
7
|
+
data.tar.gz: bdff30862931f8d0d28d0c15ccf36b70056fe65c3b588c619c9452c7f92a4a732569ac4925e68af88fe67682f49854aa809b7468ee7d81005b44fd33b1c537ba
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 2.7.8
|
data/CLAUDE.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# CLAUDE.md
|
2
|
+
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
4
|
+
|
5
|
+
## Project Overview
|
6
|
+
|
7
|
+
This is a Ruby gem that converts French words into numbers. The gem provides a single public method `StringToNumber.in_numbers(french_string)` that parses French number words and returns their numeric equivalent.
|
8
|
+
|
9
|
+
## Core Architecture
|
10
|
+
|
11
|
+
- **Main module**: `StringToNumber` in `lib/string_to_number.rb` - provides the public API
|
12
|
+
- **Optimized parser**: `StringToNumber::Parser` in `lib/string_to_number/parser.rb` - high-performance implementation
|
13
|
+
- **Original implementation**: `StringToNumber::ToNumber` in `lib/string_to_number/to_number.rb` - legacy compatibility
|
14
|
+
- **Version**: `StringToNumber::VERSION` in `lib/string_to_number/version.rb`
|
15
|
+
|
16
|
+
### Parser Architecture
|
17
|
+
|
18
|
+
The optimized parser uses:
|
19
|
+
- **WORD_VALUES**: Direct French word to number mappings (0-90, including regional variants)
|
20
|
+
- **MULTIPLIERS**: Power-of-ten multipliers (cent=2, mille=3, million=6, etc.)
|
21
|
+
- **Pre-compiled regex patterns**: Eliminate compilation overhead
|
22
|
+
- **Multi-level caching**: Instance cache + LRU conversion cache
|
23
|
+
- **Thread-safe design**: Concurrent access with mutex protection
|
24
|
+
|
25
|
+
The algorithm maintains the proven recursive parsing logic from the original while adding:
|
26
|
+
- Memoization for repeated conversions
|
27
|
+
- Instance caching to reduce initialization costs
|
28
|
+
- Optimized string operations and hash lookups
|
29
|
+
|
30
|
+
## Common Development Commands
|
31
|
+
|
32
|
+
```bash
|
33
|
+
# Install dependencies
|
34
|
+
bundle install
|
35
|
+
|
36
|
+
# Run tests
|
37
|
+
rake spec
|
38
|
+
|
39
|
+
# Run specific test
|
40
|
+
bundle exec rspec spec/string_to_number_spec.rb
|
41
|
+
|
42
|
+
# Start interactive console
|
43
|
+
rake console
|
44
|
+
# or
|
45
|
+
bundle exec irb -I lib -r string_to_number
|
46
|
+
|
47
|
+
# Install gem locally
|
48
|
+
bundle exec rake install
|
49
|
+
|
50
|
+
# Release new version (updates version.rb, creates git tag, pushes to rubygems)
|
51
|
+
bundle exec rake release
|
52
|
+
```
|
53
|
+
|
54
|
+
## Testing
|
55
|
+
|
56
|
+
Uses RSpec with comprehensive test coverage for French number parsing from 0 to millions. Tests are organized by number ranges (0-9, 10-19, 20-29, etc.) and include complex multi-word numbers.
|
57
|
+
|
58
|
+
### Performance Testing
|
59
|
+
|
60
|
+
Performance tests are available to measure and monitor the implementation's efficiency:
|
61
|
+
|
62
|
+
```bash
|
63
|
+
# Run comprehensive performance test suite
|
64
|
+
bundle exec rspec spec/performance_spec.rb
|
65
|
+
|
66
|
+
# Run standalone benchmark script
|
67
|
+
ruby -I lib benchmark.rb
|
68
|
+
|
69
|
+
# Run micro-benchmarks to identify bottlenecks
|
70
|
+
ruby -I lib microbenchmark.rb
|
71
|
+
|
72
|
+
# Run profiling analysis
|
73
|
+
ruby -I lib profile.rb
|
74
|
+
```
|
75
|
+
|
76
|
+
**Performance Characteristics (Optimized Implementation):**
|
77
|
+
- Simple numbers (0-100): ~0.001ms average, 800,000+ conversions/sec
|
78
|
+
- Medium complexity (100-1000): ~0.001ms average, 780,000+ conversions/sec
|
79
|
+
- Complex numbers (1000+): ~0.002ms average, 690,000+ conversions/sec
|
80
|
+
- Exceptional scalability: minimal performance degradation with input length
|
81
|
+
- Memory efficient: zero object creation during operation
|
82
|
+
- Intelligent caching: repeated conversions benefit from memoization
|
83
|
+
|
84
|
+
**Performance Improvements:**
|
85
|
+
- **14-460x faster** than original implementation across all test cases
|
86
|
+
- **Excellent scalability**: 1.3x degradation vs 43x in original
|
87
|
+
- **Pre-compiled regex patterns** eliminate compilation overhead
|
88
|
+
- **Instance caching** reduces initialization costs
|
89
|
+
- **Memoization** speeds up repeated conversions
|
90
|
+
- **Thread-safe** with concurrent performance >2M conversions/sec
|
91
|
+
|
92
|
+
**Usage Options:**
|
93
|
+
```ruby
|
94
|
+
# Use optimized implementation (default)
|
95
|
+
StringToNumber.in_numbers('vingt et un')
|
96
|
+
|
97
|
+
# Use original implementation for compatibility
|
98
|
+
StringToNumber.in_numbers('vingt et un', use_optimized: false)
|
99
|
+
|
100
|
+
# Cache management
|
101
|
+
StringToNumber.clear_caches!
|
102
|
+
StringToNumber.cache_stats
|
103
|
+
```
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,32 @@
|
|
1
1
|
# StringToNumber
|
2
2
|
|
3
|
-
|
3
|
+
[](https://badge.fury.io/rb/string_to_number)
|
4
|
+
[](https://github.com/FabienPiette/string_to_number/actions)
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
4
6
|
|
5
|
-
|
7
|
+
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
|
+
|
9
|
+
## ✨ Features
|
10
|
+
|
11
|
+
- **High Performance**: Up to 460x faster than naive implementations with intelligent caching
|
12
|
+
- **Thread-Safe**: Concurrent access support with proper locking mechanisms
|
13
|
+
- **Comprehensive**: Handles complex French number formats including:
|
14
|
+
- Basic numbers (zéro, un, deux...)
|
15
|
+
- Compound numbers (vingt et un, quatre-vingt-quatorze...)
|
16
|
+
- Large numbers (millions, milliards, billions...)
|
17
|
+
- Special cases (quatre-vingts, soixante-dix...)
|
18
|
+
- **Memory Efficient**: LRU cache with configurable limits
|
19
|
+
- **Backward Compatible**: Maintains compatibility with original implementation
|
20
|
+
|
21
|
+
## 🚀 Performance
|
22
|
+
|
23
|
+
| Input Size | Original | Optimized | Improvement |
|
24
|
+
|------------|----------|-----------|-------------|
|
25
|
+
| Short | 0.5ms | 0.035ms | **14x** |
|
26
|
+
| Medium | 2.1ms | 0.045ms | **47x** |
|
27
|
+
| Long | 23ms | 0.05ms | **460x** |
|
28
|
+
|
29
|
+
## 📦 Installation
|
6
30
|
|
7
31
|
Add this line to your application's Gemfile:
|
8
32
|
|
@@ -12,45 +36,176 @@ gem 'string_to_number'
|
|
12
36
|
|
13
37
|
And then execute:
|
14
38
|
|
15
|
-
|
39
|
+
```bash
|
40
|
+
$ bundle install
|
41
|
+
```
|
16
42
|
|
17
43
|
Or install it yourself as:
|
18
44
|
|
19
|
-
|
45
|
+
```bash
|
46
|
+
$ gem install string_to_number
|
47
|
+
```
|
48
|
+
|
49
|
+
## 🔧 Usage
|
20
50
|
|
21
|
-
|
51
|
+
### Basic Usage
|
22
52
|
|
23
53
|
```ruby
|
24
54
|
require 'string_to_number'
|
25
55
|
|
26
|
-
|
27
|
-
#=> 0
|
56
|
+
# Simple numbers
|
57
|
+
StringToNumber.in_numbers('zéro') #=> 0
|
58
|
+
StringToNumber.in_numbers('quinze') #=> 15
|
59
|
+
StringToNumber.in_numbers('cent') #=> 100
|
60
|
+
|
61
|
+
# Compound numbers
|
62
|
+
StringToNumber.in_numbers('vingt et un') #=> 21
|
63
|
+
StringToNumber.in_numbers('quatre-vingt-quatorze') #=> 94
|
64
|
+
StringToNumber.in_numbers('soixante-dix') #=> 70
|
65
|
+
|
66
|
+
# Large numbers
|
67
|
+
StringToNumber.in_numbers('mille deux cent trente-quatre') #=> 1234
|
68
|
+
StringToNumber.in_numbers('un million') #=> 1_000_000
|
69
|
+
StringToNumber.in_numbers('trois milliards') #=> 3_000_000_000
|
70
|
+
|
71
|
+
# Complex expressions
|
72
|
+
StringToNumber.in_numbers('neuf mille neuf cent quatre-vingt-dix-neuf') #=> 9999
|
73
|
+
StringToNumber.in_numbers('deux millions trois cent mille') #=> 2_300_000
|
74
|
+
```
|
75
|
+
|
76
|
+
### Advanced Features
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# Validation
|
80
|
+
StringToNumber.valid_french_number?('vingt et un') #=> true
|
81
|
+
StringToNumber.valid_french_number?('hello world') #=> false
|
82
|
+
|
83
|
+
# Cache management
|
84
|
+
StringToNumber.clear_caches! # Clear all internal caches
|
85
|
+
stats = StringToNumber.cache_stats
|
86
|
+
puts "Cache hit ratio: #{stats[:cache_hit_ratio]}"
|
87
|
+
|
88
|
+
# Backward compatibility mode
|
89
|
+
StringToNumber.in_numbers('cent', use_optimized: false) #=> 100
|
90
|
+
```
|
91
|
+
|
92
|
+
### Supported Number Formats
|
93
|
+
|
94
|
+
| Range | Examples |
|
95
|
+
|-------|----------|
|
96
|
+
| 0-19 | zéro, un, deux, trois, quatre, cinq, six, sept, huit, neuf, dix, onze, douze, treize, quatorze, quinze, seize, dix-sept, dix-huit, dix-neuf |
|
97
|
+
| 20-99 | vingt, trente, quarante, cinquante, soixante, soixante-dix, quatre-vingts, quatre-vingt-dix |
|
98
|
+
| 100+ | cent, mille, million, milliard, billion |
|
99
|
+
| Compounds | vingt et un, quatre-vingt-quatorze, deux mille trois |
|
100
|
+
|
101
|
+
## ⚡ Performance Tips
|
102
|
+
|
103
|
+
1. **Reuse conversions**: The gem automatically caches results for better performance
|
104
|
+
2. **Batch processing**: Use the optimized parser (default) for better throughput
|
105
|
+
3. **Memory management**: Call `clear_caches!` periodically if processing many unique inputs
|
106
|
+
4. **Thread safety**: The gem is thread-safe and can be used in concurrent environments
|
107
|
+
|
108
|
+
## 🧪 Development
|
109
|
+
|
110
|
+
After checking out the repo, run `bin/setup` to install dependencies:
|
28
111
|
|
29
|
-
|
30
|
-
|
112
|
+
```bash
|
113
|
+
$ git clone https://github.com/FabienPiette/string_to_number.git
|
114
|
+
$ cd string_to_number
|
115
|
+
$ bin/setup
|
116
|
+
```
|
117
|
+
|
118
|
+
### Running Tests
|
119
|
+
|
120
|
+
```bash
|
121
|
+
# Run all tests
|
122
|
+
$ rake spec
|
123
|
+
|
124
|
+
# Run performance tests
|
125
|
+
$ ruby benchmark.rb
|
126
|
+
|
127
|
+
# Run specific test files
|
128
|
+
$ rspec spec/string_to_number_spec.rb
|
129
|
+
```
|
31
130
|
|
32
|
-
|
33
|
-
#=> 94
|
131
|
+
### Performance Benchmarking
|
34
132
|
|
35
|
-
|
36
|
-
|
133
|
+
```bash
|
134
|
+
# Compare implementations
|
135
|
+
$ ruby performance_comparison.rb
|
37
136
|
|
38
|
-
|
39
|
-
|
137
|
+
# Detailed micro-benchmarks
|
138
|
+
$ ruby microbenchmark.rb
|
40
139
|
```
|
41
140
|
|
42
|
-
|
141
|
+
### Interactive Console
|
142
|
+
|
143
|
+
```bash
|
144
|
+
$ bin/console
|
145
|
+
# => Interactive prompt for experimentation
|
146
|
+
```
|
147
|
+
|
148
|
+
## 🏗️ Architecture
|
149
|
+
|
150
|
+
The gem uses a dual-architecture approach:
|
151
|
+
|
152
|
+
- **Optimized Parser** (`StringToNumber::Parser`): High-performance implementation with caching
|
153
|
+
- **Original Implementation** (`StringToNumber::ToNumber`): Reference implementation for compatibility
|
154
|
+
|
155
|
+
Key performance optimizations:
|
156
|
+
- Pre-compiled regex patterns
|
157
|
+
- LRU caching with thread-safe access
|
158
|
+
- Memoized parser instances
|
159
|
+
- Zero-allocation number matching
|
160
|
+
|
161
|
+
## 🤝 Contributing
|
162
|
+
|
163
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/FabienPiette/string_to_number.
|
164
|
+
|
165
|
+
### Development Process
|
166
|
+
|
167
|
+
1. Fork the repository
|
168
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
169
|
+
3. Write tests for your changes
|
170
|
+
4. Ensure all tests pass (`rake spec`)
|
171
|
+
5. Run performance tests to avoid regressions
|
172
|
+
6. Commit your changes (`git commit -am 'Add amazing feature'`)
|
173
|
+
7. Push to the branch (`git push origin feature/amazing-feature`)
|
174
|
+
8. Open a Pull Request
|
175
|
+
|
176
|
+
### Code of Conduct
|
177
|
+
|
178
|
+
This project is intended to be a safe, welcoming space for collaboration. Contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
179
|
+
|
180
|
+
## 📋 Requirements
|
181
|
+
|
182
|
+
- Ruby 2.5 or higher
|
183
|
+
- No external dependencies (uses only Ruby standard library)
|
184
|
+
|
185
|
+
## 🐛 Troubleshooting
|
186
|
+
|
187
|
+
### Common Issues
|
188
|
+
|
189
|
+
**Q: Numbers aren't parsing correctly**
|
190
|
+
A: Ensure your input uses proper French number words. Use `valid_french_number?` to validate input.
|
191
|
+
|
192
|
+
**Q: Performance seems slow**
|
193
|
+
A: Make sure you're using the default optimized parser. Check cache statistics with `cache_stats`.
|
43
194
|
|
44
|
-
|
195
|
+
**Q: Memory usage is high**
|
196
|
+
A: Call `clear_caches!` periodically if processing many unique number strings.
|
45
197
|
|
46
|
-
|
198
|
+
## 📝 Changelog
|
47
199
|
|
48
|
-
|
200
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history and updates.
|
49
201
|
|
50
|
-
|
202
|
+
## 📄 License
|
51
203
|
|
204
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
52
205
|
|
53
|
-
##
|
206
|
+
## 🙏 Acknowledgments
|
54
207
|
|
55
|
-
|
208
|
+
- Original implementation by [Fabien Piette](https://github.com/FabienPiette)
|
209
|
+
- Performance optimizations and enhancements
|
210
|
+
- Community contributors and testers
|
56
211
|
|
data/benchmark.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# Performance benchmark script for StringToNumber gem
|
5
|
+
# Run with: ruby benchmark.rb
|
6
|
+
|
7
|
+
require_relative 'lib/string_to_number'
|
8
|
+
require 'benchmark'
|
9
|
+
|
10
|
+
class StringToNumberBenchmark
|
11
|
+
# Test data organized by complexity
|
12
|
+
TEST_CASES = {
|
13
|
+
simple: [
|
14
|
+
'un', 'vingt', 'cent', 'mille'
|
15
|
+
],
|
16
|
+
medium: [
|
17
|
+
'vingt et un', 'deux cent cinquante', 'mille deux cent'
|
18
|
+
],
|
19
|
+
complex: [
|
20
|
+
'trois milliards cinq cents millions',
|
21
|
+
'soixante-quinze million trois cent quarante six mille sept cent quatre-vingt-dix neuf'
|
22
|
+
],
|
23
|
+
edge_cases: [
|
24
|
+
'VINGT', 'une', 'septante', 'quatre-vingts'
|
25
|
+
]
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
def self.run_benchmark
|
29
|
+
puts "StringToNumber Performance Benchmark"
|
30
|
+
puts "=" * 50
|
31
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
32
|
+
puts "Platform: #{RUBY_PLATFORM}"
|
33
|
+
puts
|
34
|
+
|
35
|
+
# Warm up
|
36
|
+
puts "Warming up..."
|
37
|
+
TEST_CASES.values.flatten.each { |text| StringToNumber.in_numbers(text) }
|
38
|
+
puts
|
39
|
+
|
40
|
+
total_results = {}
|
41
|
+
|
42
|
+
TEST_CASES.each do |category, test_cases|
|
43
|
+
puts "#{category.to_s.capitalize} Numbers:"
|
44
|
+
puts "-" * 30
|
45
|
+
|
46
|
+
results = benchmark_category(test_cases)
|
47
|
+
total_results[category] = results
|
48
|
+
|
49
|
+
puts "Cases: #{test_cases.size}"
|
50
|
+
puts "Total time: #{results[:total_time].round(4)}s"
|
51
|
+
puts "Average per conversion: #{results[:avg_time_ms].round(4)}ms"
|
52
|
+
puts "Conversions per second: #{results[:ops_per_sec].round(0)}"
|
53
|
+
puts
|
54
|
+
|
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 ? '...' : ''}'"
|
64
|
+
end
|
65
|
+
puts
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Summary
|
70
|
+
puts "=" * 50
|
71
|
+
puts "PERFORMANCE SUMMARY"
|
72
|
+
puts "=" * 50
|
73
|
+
|
74
|
+
total_results.each do |category, results|
|
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"
|
80
|
+
end
|
81
|
+
|
82
|
+
puts "#{category.to_s.capitalize.ljust(12)} #{status.ljust(15)} #{results[:avg_time_ms].round(4)}ms avg"
|
83
|
+
end
|
84
|
+
|
85
|
+
puts
|
86
|
+
puts "Memory efficiency test..."
|
87
|
+
test_memory_usage
|
88
|
+
|
89
|
+
puts
|
90
|
+
puts "Scalability test..."
|
91
|
+
test_scalability
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def self.benchmark_category(test_cases, iterations = 2000)
|
97
|
+
total_time = Benchmark.realtime do
|
98
|
+
test_cases.each do |text|
|
99
|
+
iterations.times do
|
100
|
+
StringToNumber.in_numbers(text)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
total_conversions = test_cases.size * iterations
|
106
|
+
avg_time_ms = (total_time / total_conversions) * 1000
|
107
|
+
ops_per_sec = total_conversions / total_time
|
108
|
+
|
109
|
+
{
|
110
|
+
total_time: total_time,
|
111
|
+
avg_time_ms: avg_time_ms,
|
112
|
+
ops_per_sec: ops_per_sec
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.test_memory_usage
|
117
|
+
# Test memory efficiency
|
118
|
+
if Object.const_defined?(:ObjectSpace)
|
119
|
+
GC.start
|
120
|
+
initial_objects = ObjectSpace.count_objects[:TOTAL]
|
121
|
+
|
122
|
+
# Perform intensive operations
|
123
|
+
500.times do
|
124
|
+
TEST_CASES.values.flatten.each { |text| StringToNumber.in_numbers(text) }
|
125
|
+
end
|
126
|
+
|
127
|
+
GC.start
|
128
|
+
final_objects = ObjectSpace.count_objects[:TOTAL]
|
129
|
+
object_growth = final_objects - initial_objects
|
130
|
+
|
131
|
+
puts "Object creation: #{object_growth} new objects (#{object_growth > 1000 ? '🔴 High' : '🟢 Low'})"
|
132
|
+
else
|
133
|
+
puts "Memory tracking not available on this platform"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.test_scalability
|
138
|
+
# Test how performance scales with input complexity
|
139
|
+
inputs = [
|
140
|
+
'un', # 2 chars
|
141
|
+
'vingt et un', # 11 chars
|
142
|
+
'mille deux cent trente-quatre', # 29 chars
|
143
|
+
'trois milliards cinq cents millions deux cent mille et une' # 58 chars
|
144
|
+
]
|
145
|
+
|
146
|
+
puts "Input length vs. performance:"
|
147
|
+
|
148
|
+
results = inputs.map do |input|
|
149
|
+
time = Benchmark.realtime do
|
150
|
+
1000.times { StringToNumber.in_numbers(input) }
|
151
|
+
end
|
152
|
+
avg_ms = (time / 1000) * 1000
|
153
|
+
|
154
|
+
{ length: input.length, time: avg_ms, input: input }
|
155
|
+
end
|
156
|
+
|
157
|
+
results.each do |result|
|
158
|
+
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)"
|
162
|
+
end
|
163
|
+
|
164
|
+
# Check if performance degrades reasonably
|
165
|
+
worst_ratio = results.last[:time] / results.first[:time]
|
166
|
+
if worst_ratio < 10
|
167
|
+
puts "✅ Scalability: Good (#{worst_ratio.round(1)}x degradation)"
|
168
|
+
else
|
169
|
+
puts "❌ Scalability: Poor (#{worst_ratio.round(1)}x degradation)"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Run the benchmark
|
175
|
+
if __FILE__ == $0
|
176
|
+
StringToNumberBenchmark.run_benchmark
|
177
|
+
end
|