factorial-cached 0.0.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.
- data/LICENSE +20 -0
- data/README.md +72 -0
- data/lib/Factorial.rb~ +69 -0
- data/lib/Integer.rb~ +7 -0
- data/lib/factorial-cached.rb +2 -0
- data/lib/factorial-cached.rb~ +0 -0
- data/lib/factorial-cached/Factorial.rb +93 -0
- data/lib/factorial-cached/Integer.rb +7 -0
- data/lib/factorial-cached/Integer.rb~ +7 -0
- metadata +56 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Yiğitcan UÇUM
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
ruby-factorial-cached
|
2
|
+
=====================
|
3
|
+
|
4
|
+
factorial-cached is a gem which aims to fasten your consecutively made factorial operations with caching. This gem was half-way done because of a little Project Euler adventure of mine. Please make any pull requests that you think will fasten the operations and i will check it out and update the gem on rubygems asap.
|
5
|
+
|
6
|
+
Usage
|
7
|
+
=====
|
8
|
+
|
9
|
+
### Installation
|
10
|
+
|
11
|
+
```
|
12
|
+
gem install factorial-cached
|
13
|
+
```
|
14
|
+
|
15
|
+
### Options
|
16
|
+
|
17
|
+
You can pass some parameters to factorial method to your needs. Above are the options and their default values.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
|
21
|
+
# Caching
|
22
|
+
|
23
|
+
:cache_none # Doesn't caches any calculated factorial.
|
24
|
+
:cache_all # Caches all the possible invocation/iteration results. This option is not recommended if you will work with high numbers.
|
25
|
+
:cache_one # Caches only the given numbers results. (DEFAULT)
|
26
|
+
|
27
|
+
# Algorithm
|
28
|
+
|
29
|
+
:iterative # Iterative implementation of the Factorial Algorithm. Good if you will calculate high numbers.
|
30
|
+
:recursive # Recursive implementation of the Factorial Algorithm. Good if you want speed on low numbers.
|
31
|
+
:auto # Iterative if number > 100.000, Recursive if below or equal. (DEFAULT)
|
32
|
+
|
33
|
+
# Closest
|
34
|
+
|
35
|
+
:value # Returns value of the closest factorial.
|
36
|
+
:factorial # Returns closest cached factorial.
|
37
|
+
|
38
|
+
```
|
39
|
+
|
40
|
+
### Code
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
require 'factorial-cached'
|
44
|
+
|
45
|
+
5.factorial # => 120 - Caches 5 factorial only.
|
46
|
+
8.factorial(:cache_all) #=> 40320 - Caches through 6..8 factorial.
|
47
|
+
7.factorial #=> 5040 - Returns by Dividing cached 8! / 8
|
48
|
+
|
49
|
+
Factorial::factorial(5, :iterative, :cache_all) #=> Same deal as the Integer#factorial
|
50
|
+
|
51
|
+
Factorial::closest(5) #=> 5 - Returns closest cached factorial by the given number.
|
52
|
+
Factorial::closest(5, :value) #=> 120 - Returns closest cached factorial's value by the given number.
|
53
|
+
|
54
|
+
Factorial::empty_cache() # Empties cache if you don't want to have memory issues.
|
55
|
+
Factorial::empty_cache(5..8) # Emtpies cache through 5..8 factorial.
|
56
|
+
|
57
|
+
Factorial::get_cache() # => { 0 => 1} in this case.
|
58
|
+
|
59
|
+
Factorial::toggle(:cache, :cache_none) # Toggles default of caching to none, further factorial calculations will not be cached by default.
|
60
|
+
Factorial::toggle(:algorithm, :iterative) # Togglest default algorithm to iterative algorithm.
|
61
|
+
Factorial::toggle(:closest, :value) # Closest now returns value of the factorial default.
|
62
|
+
|
63
|
+
5.factorial => Returns 5, caches nothing.
|
64
|
+
5.factorial(:cache_one) => Calculates 5!, caches 5! only. (This is the default behaviour of this gem)
|
65
|
+
5.factorial => Returns 5! from cache.
|
66
|
+
|
67
|
+
```
|
68
|
+
|
69
|
+
License
|
70
|
+
=======
|
71
|
+
|
72
|
+
MIT: [External Link to License](http://opensource.org/licenses/MIT)
|
data/lib/Factorial.rb~
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
class Factorial
|
2
|
+
|
3
|
+
@@cache = {
|
4
|
+
0 => 1, 1 => 1, 2 => 2, 3 => 6, 4 => 24, 5 => 120, 6 => 720, 7 => 5040, 8 => 40320, 9 => 3628800, 10 => 36288000, 11 => 39916800, 12 => 479001600, # Below 32 bit
|
5
|
+
14 => 87178291200, 20 => 2432902008176640000, 30 => 265252859812191058636308480000000, 50 => 30414093201713378043612608166064768844377641568960512000000000000, # Below are milestones for 1-100!
|
6
|
+
70 => 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000,
|
7
|
+
100 => 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
8
|
+
};
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def closest(number, option = :factorial)
|
13
|
+
close = (@@cache.keys.sort{ |x, y| (x - number).abs <=> (y - number).abs })[0];
|
14
|
+
return option == :value ? @@cache[close] : close;
|
15
|
+
end
|
16
|
+
|
17
|
+
def recursive_factorial(number, cache = :cache, close = -1)
|
18
|
+
|
19
|
+
return @@cache[number] if number == close;
|
20
|
+
|
21
|
+
if close == -1 then
|
22
|
+
close = self.closest(number);
|
23
|
+
puts "Using Cache: " + close.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
result = close < number ? number * recursive_factorial(number - 1, cache, close) : recursive_factorial(number + 1, cache, close) / (number + 1);
|
27
|
+
|
28
|
+
@@cache[number] = result if cache == :cache_all;
|
29
|
+
|
30
|
+
return result;
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
def iterative_factorial(number, cache = :cache)
|
35
|
+
|
36
|
+
closest = self.closest(number);
|
37
|
+
puts "Using Cache: " + close.to_s
|
38
|
+
loopThrough = closest < number ? ((closest + 1)..number) : ((number + 1)..closest);
|
39
|
+
result = @@cache[closest];
|
40
|
+
|
41
|
+
for i in loopThrough do
|
42
|
+
|
43
|
+
if closest < number then result *= i; else result /= i; end
|
44
|
+
@@cache[i] = result if cache == :cache_all;
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
return result;
|
49
|
+
end
|
50
|
+
|
51
|
+
def factorial(number, *options)
|
52
|
+
|
53
|
+
return @@cache[number] if @@cache.has_key?(number);
|
54
|
+
return 1 if number <= 0;
|
55
|
+
|
56
|
+
factorial = method(options.include?(:iterative) || number > 100000 ? :iterative_factorial : :recursive_factorial);
|
57
|
+
cache = options.include?(:cache_none) ? :cache_none : options.include?(:cache_all) ? :cache_all : :cache;
|
58
|
+
|
59
|
+
result = factorial.call(number, cache);
|
60
|
+
|
61
|
+
@@cache[number] = result if cache != :cache_none;
|
62
|
+
|
63
|
+
return factorial;
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/Integer.rb~
ADDED
File without changes
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class Factorial
|
2
|
+
|
3
|
+
@@cache = {
|
4
|
+
0 => 1, 1 => 1, 2 => 2, 3 => 6, 4 => 24, 5 => 120, 6 => 720, 7 => 5040, 8 => 40320, 9 => 3628800, 10 => 36288000, 11 => 39916800, 12 => 479001600, # Below 32 bit
|
5
|
+
14 => 87178291200, 20 => 2432902008176640000, 30 => 265252859812191058636308480000000, 50 => 30414093201713378043612608166064768844377641568960512000000000000, # Milestones for 1-100!
|
6
|
+
70 => 11978571669969891796072783721689098736458938142546425857555362864628009582789845319680000000000000000,
|
7
|
+
100 => 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
|
8
|
+
};
|
9
|
+
|
10
|
+
@@default = { :cache => :cache_one, :algorithm => :recursive, :closest => :factorial };
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
def empty_cache( range = nil )
|
15
|
+
if range != nil then
|
16
|
+
range.each{ |key| @@cache.delete(key); };
|
17
|
+
@@cache[0] = 1;
|
18
|
+
else @@cache = {0 => 1}; end
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_cache()
|
22
|
+
return @@cache;
|
23
|
+
end
|
24
|
+
|
25
|
+
def toggle(setting, default)
|
26
|
+
if setting == :cache then
|
27
|
+
@@default[:cache] = default;
|
28
|
+
elsif setting == :algorithm then
|
29
|
+
@@default[:algorithm] = default;
|
30
|
+
elsif setting == :closest then
|
31
|
+
@@default[:closest] = default;
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def closest(number, option = @@default[:closest])
|
36
|
+
close = (@@cache.keys.sort{ |x, y| (x - number).abs <=> (y - number).abs })[0];
|
37
|
+
return option == :value ? @@cache[close] : close;
|
38
|
+
end
|
39
|
+
|
40
|
+
def recursive_factorial(number, cache = @@default[:cache], close = -1)
|
41
|
+
|
42
|
+
return @@cache[number] if close == number;
|
43
|
+
|
44
|
+
if close == -1 then
|
45
|
+
close = self.closest(number, :factorial);
|
46
|
+
end
|
47
|
+
|
48
|
+
result = close < number ? number * recursive_factorial(number - 1, cache, close) : recursive_factorial(number + 1, cache, close) / (number + 1);
|
49
|
+
|
50
|
+
@@cache[number] = result if cache == :cache_all;
|
51
|
+
|
52
|
+
return result;
|
53
|
+
end
|
54
|
+
|
55
|
+
def iterative_factorial(number, cache = @@default[:cache])
|
56
|
+
|
57
|
+
closest = self.closest(number, :factorial);
|
58
|
+
loopThrough = closest < number ? ((closest + 1)..number) : ((number + 1)..closest);
|
59
|
+
result = @@cache[closest];
|
60
|
+
|
61
|
+
for i in loopThrough do
|
62
|
+
|
63
|
+
if closest < number then result *= i; else result /= i; end
|
64
|
+
@@cache[i] = result if cache == :cache_all;
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
return result;
|
69
|
+
end
|
70
|
+
|
71
|
+
def factorial(number, *options)
|
72
|
+
|
73
|
+
return @@cache[number] if @@cache.has_key?(number);
|
74
|
+
return 1 if (number = number.to_i) <= 0 || !number.is_a?(Integer);
|
75
|
+
|
76
|
+
factorial = method(options.include?(:iterative) ? :iterative_factorial :
|
77
|
+
options.include?(:recursive) ? :recursive_factorial :
|
78
|
+
options.include?(:auto) ? (number > 100000 ? :iterative_factorial : :recursive_factorial) :
|
79
|
+
@@default[:algorithm] == :recursive ? :recursive_factorial :
|
80
|
+
@@default[:algorithm] == :auto ? (number > 100000 ? :iterative_factorial : recursive_factorial) : :iterative_factorial);
|
81
|
+
cache = options.include?(:cache_none) ? :cache_none : options.include?(:cache_all) ? :cache_all : options.include?(:cache_one) ? :cache_one : @@default[:cache];
|
82
|
+
|
83
|
+
result = factorial.call(number, cache);
|
84
|
+
|
85
|
+
@@cache[number] = result if cache != :cache_none;
|
86
|
+
|
87
|
+
return result;
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: factorial-cached
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yiğitcan UÇUM
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-02-06 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: This gem is specifically made for getting your factorial operations faster.
|
15
|
+
This gem was half made already when i decided to make it because of my needs of
|
16
|
+
factorial operations in Project Euler.
|
17
|
+
email: yigitcan@hotmail.com.tr
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- LICENSE
|
23
|
+
- README.md
|
24
|
+
- lib/factorial-cached.rb~
|
25
|
+
- lib/Factorial.rb~
|
26
|
+
- lib/factorial-cached/Integer.rb
|
27
|
+
- lib/factorial-cached/Factorial.rb
|
28
|
+
- lib/factorial-cached/Integer.rb~
|
29
|
+
- lib/Integer.rb~
|
30
|
+
- lib/factorial-cached.rb
|
31
|
+
homepage: http://rubygems.org/gems/factorial-cached
|
32
|
+
licenses:
|
33
|
+
- MIT
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
none: false
|
46
|
+
requirements:
|
47
|
+
- - ! '>='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0'
|
50
|
+
requirements: []
|
51
|
+
rubyforge_project:
|
52
|
+
rubygems_version: 1.8.11
|
53
|
+
signing_key:
|
54
|
+
specification_version: 3
|
55
|
+
summary: A gem for making your factorial operations faster.
|
56
|
+
test_files: []
|