Class: Factoradic
- Inherits:
-
Object
- Object
- Factoradic
- Defined in:
- lib/factoradic.rb,
lib/factoradic/version.rb
Constant Summary collapse
- DEFAULT_OPTIONS =
{ # disabling this will save ram when computing # very large (Bignum) factorial values memoize_factorial_values: false, # the separator used between placex in factorial base separator: ':' }
- VERSION =
'1.0.0'
Class Attribute Summary collapse
-
.options ⇒ Object
Returns the value of attribute options.
Class Method Summary collapse
- .autoconvert(str) ⇒ Object
- .basic_factorial(n) ⇒ Object
- .convert_decimal_to_factoradic(decimal) ⇒ Object (also: d2f)
- .convert_factoradic_to_decimal(str) ⇒ Object (also: f2d)
- .factorial(n) ⇒ Object
- .memoized_factorial(n) ⇒ Object
- .nonstandard_separator? ⇒ Boolean
- .parse(str) ⇒ Object
- .parse_decimal(decimal) ⇒ Object
- .parse_factoradic(str) ⇒ Object
- .string_is_factoradic?(str) ⇒ Boolean
- .valid_factoradic_digits?(digit_list) ⇒ Boolean
Instance Method Summary collapse
- #[](i) ⇒ Object
- #[]=(i, rvalue) ⇒ Object
- #digits=(new_digits) ⇒ Object
-
#initialize ⇒ Factoradic
constructor
A new instance of Factoradic.
- #inspect ⇒ Object
- #options ⇒ Object
- #parse_factoradic(str) ⇒ Object
- #recompute_digits! ⇒ Object
- #recompute_value! ⇒ Object
- #to_i ⇒ Object
- #to_s(separator = options.separator) ⇒ Object
- #value=(new_value) ⇒ Object
Constructor Details
#initialize ⇒ Factoradic
Returns a new instance of Factoradic.
112 113 114 115 |
# File 'lib/factoradic.rb', line 112 def initialize @value = 0 @digits = [0] end |
Class Attribute Details
.options ⇒ Object
Returns the value of attribute options.
21 22 23 |
# File 'lib/factoradic.rb', line 21 def @options end |
Class Method Details
.autoconvert(str) ⇒ Object
65 66 67 68 69 70 71 |
# File 'lib/factoradic.rb', line 65 def autoconvert(str) if string_is_factoradic?(str) convert_factoradic_to_decimal(str) else convert_decimal_to_factoradic(str) end end |
.basic_factorial(n) ⇒ Object
99 100 101 |
# File 'lib/factoradic.rb', line 99 def basic_factorial(n) (1..n).reduce(1, :*) end |
.convert_decimal_to_factoradic(decimal) ⇒ Object Also known as: d2f
79 80 81 82 |
# File 'lib/factoradic.rb', line 79 def convert_decimal_to_factoradic(decimal) f = parse_decimal(decimal) f.to_s end |
.convert_factoradic_to_decimal(str) ⇒ Object Also known as: f2d
73 74 75 76 |
# File 'lib/factoradic.rb', line 73 def convert_factoradic_to_decimal(str) f = parse_factoradic(str) f.to_i.to_s(10) end |
.factorial(n) ⇒ Object
103 104 105 106 107 108 109 |
# File 'lib/factoradic.rb', line 103 def factorial(n) if .memoize_factorial_values memoized_factorial(n) else basic_factorial(n) end end |
.memoized_factorial(n) ⇒ Object
91 92 93 94 95 96 97 |
# File 'lib/factoradic.rb', line 91 def memoized_factorial(n) if @factorial_sequence.length > n @factorial_sequence[n] else @factorial_sequence[n] = n * memoized_factorial(n - 1) end end |
.nonstandard_separator? ⇒ Boolean
23 24 25 |
# File 'lib/factoradic.rb', line 23 def nonstandard_separator? .separator != DEFAULT_OPTIONS[:separator] end |
.parse(str) ⇒ Object
57 58 59 60 61 62 63 |
# File 'lib/factoradic.rb', line 57 def parse(str) if string_is_factoradic?(str) [parse_factoradic(str), :factorial] else [parse_decimal(str), :decimal] end end |
.parse_decimal(decimal) ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/factoradic.rb', line 42 def parse_decimal(decimal) intvalue = case decimal when Integer decimal when String decimal.to_i(10) else raise ArgumentError, "Expected an Integer or String{" end new.tap do |f| f.value = intvalue end end |
.parse_factoradic(str) ⇒ Object
36 37 38 39 40 |
# File 'lib/factoradic.rb', line 36 def parse_factoradic(str) new.tap do |f| f.parse_factoradic(str) end end |
.string_is_factoradic?(str) ⇒ Boolean
27 28 29 30 31 32 33 34 |
# File 'lib/factoradic.rb', line 27 def string_is_factoradic?(str) re = if nonstandard_separator? /\A\d+([#{.separator}]\d+)+\Z/ else /\A\d+([,:]\d+)+\Z/ end !!(str =~ re) end |
.valid_factoradic_digits?(digit_list) ⇒ Boolean
85 86 87 88 89 |
# File 'lib/factoradic.rb', line 85 def valid_factoradic_digits?(digit_list) digit_list.reverse.map.with_index do |digit, idx| (digit >= 0) && (digit <= idx) end.all?(true) end |
Instance Method Details
#[](i) ⇒ Object
141 142 143 |
# File 'lib/factoradic.rb', line 141 def [](i) @digits[i] end |
#[]=(i, rvalue) ⇒ Object
145 146 147 148 149 |
# File 'lib/factoradic.rb', line 145 def []=(i, rvalue) new_places = @digits.dup new_places[i] = rvalue.to_i self.digits = new_digits end |
#digits=(new_digits) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/factoradic.rb', line 161 def digits=(new_digits) new_digits = new_digits.map do |x| if x.nil? 0 else x end end unless Factoradic.valid_factoradic_digits?(new_digits) raise ArgumentError, "Invalid factoradic digits: #{new_digits.inspect}" end @digits = new_digits recompute_value! end |
#inspect ⇒ Object
191 192 193 |
# File 'lib/factoradic.rb', line 191 def inspect "#<Factoradic #{to_s}>" end |
#options ⇒ Object
117 118 119 |
# File 'lib/factoradic.rb', line 117 def self.class. end |
#parse_factoradic(str) ⇒ Object
151 152 153 154 155 156 157 158 159 |
# File 'lib/factoradic.rb', line 151 def parse_factoradic(str) sep = if Factoradic.nonstandard_separator? /[#{Factoradic..separator}]/ else /[,:]/ end self.digits = str.split(sep).map{ |x| x.to_i } end |
#recompute_digits! ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/factoradic.rb', line 121 def recompute_digits! x = @value divisor = 2 @digits = [0] while x > 0 x, r = x.divmod(divisor) @digits.push(r) divisor += 1 end @digits.reverse! end |
#recompute_value! ⇒ Object
135 136 137 138 139 |
# File 'lib/factoradic.rb', line 135 def recompute_value! @value = @digits.reverse.map.with_index do |digit, idx| digit * Factoradic.factorial(idx) end.reduce(&:+) end |
#to_i ⇒ Object
187 188 189 |
# File 'lib/factoradic.rb', line 187 def to_i @value end |
#to_s(separator = options.separator) ⇒ Object
183 184 185 |
# File 'lib/factoradic.rb', line 183 def to_s(separator = .separator) @digits.join(separator) end |
#value=(new_value) ⇒ Object
178 179 180 181 |
# File 'lib/factoradic.rb', line 178 def value=(new_value) @value = new_value.to_i recompute_digits! end |