huge_enumerable 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -20
- data/Gemfile +3 -3
- data/LICENSE.txt +22 -22
- data/README.md +29 -29
- data/Rakefile +17 -17
- data/huge_enumerable.gemspec +28 -28
- data/lib/huge_enumerable.rb +362 -357
- data/lib/huge_enumerable/huge_collection.rb +83 -83
- data/lib/huge_enumerable/huge_combination.rb +112 -118
- data/lib/huge_enumerable/huge_permutation.rb +80 -67
- data/lib/huge_enumerable/huge_product.rb +77 -77
- data/lib/huge_enumerable/version.rb +4 -4
- data/spec/lib/huge_enumerable/huge_collection_spec.rb +32 -32
- data/spec/lib/huge_enumerable/huge_combination_spec.rb +38 -37
- data/spec/lib/huge_enumerable/huge_permutation_spec.rb +38 -37
- data/spec/lib/huge_enumerable/huge_product_spec.rb +34 -34
- data/spec/lib/huge_enumerable_spec.rb +641 -641
- metadata +97 -118
@@ -1,83 +1,83 @@
|
|
1
|
-
require 'huge_enumerable'
|
2
|
-
# The simplest form of a HugeEnumerable.
|
3
|
-
# This class can be used for large arrays or anything else that responds to [].
|
4
|
-
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
-
# It only has to be able to return the element mapped to the index given to [].
|
6
|
-
# ==== Examples
|
7
|
-
#
|
8
|
-
# Using HugeCollection directly:
|
9
|
-
#
|
10
|
-
# original_array = ('a'..'z').to_a
|
11
|
-
# collection = HugeCollection.new(original_array)
|
12
|
-
# collection.shuffle!
|
13
|
-
# original_array[0..4] # => ["a", "b", "c", "d", "e"]
|
14
|
-
# collection[0..4] # => ["j", "a", "r", "i", "z"]
|
15
|
-
#
|
16
|
-
#
|
17
|
-
# Subclassing HugeCollection
|
18
|
-
#
|
19
|
-
# class StringNext < HugeCollection
|
20
|
-
#
|
21
|
-
# def initialize(size)
|
22
|
-
# @collection_size = size
|
23
|
-
# super ('a'..'z').to_a
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# private
|
27
|
-
#
|
28
|
-
# def fetch(index)
|
29
|
-
# result = ""
|
30
|
-
# index += 1
|
31
|
-
# while index > 0
|
32
|
-
# index -= 1
|
33
|
-
# result.prepend super(index % 26)
|
34
|
-
# index /= 26
|
35
|
-
# end
|
36
|
-
# result
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# googol = 10*100
|
42
|
-
# collection = StringNext.new(googol)
|
43
|
-
# collection.size # => 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
44
|
-
# collection[0] # => "a"
|
45
|
-
# collection[-1] # => "zhxrtplbmwaiwcqlzpmglpziaegsdivmbvlnssusbjtbcgywaycqnhxztqwwikxvrsptazpp"
|
46
|
-
# collection[googol / 2] # => "dlijhfafxmqxnusmhfpshmdmopvodxfnkfgivwvnejaapyxmynutdlmjhxxqrykiiuizzhi"
|
47
|
-
# collection.shuffle!
|
48
|
-
# collection[0] # => "bipzqqzayczkgsmaseflwktpsotzclcjsqlnnjaciaawufpojywxflknuddhqkilhoedacn"
|
49
|
-
#
|
50
|
-
class HugeCollection < HugeEnumerable
|
51
|
-
|
52
|
-
# Create a new HugeCollection
|
53
|
-
#
|
54
|
-
# ==== Attributes
|
55
|
-
#
|
56
|
-
# * +enumerable+ - Any enumerable that responds to []
|
57
|
-
#
|
58
|
-
# ==== Options
|
59
|
-
#
|
60
|
-
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
61
|
-
# * +:rng+ - The random number generator to use.
|
62
|
-
def initialize(enumerable, max_array_size = nil, rng = nil)
|
63
|
-
@enum = enumerable
|
64
|
-
super(max_array_size, rng)
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
attr_accessor :enum
|
70
|
-
|
71
|
-
def collection_size
|
72
|
-
@collection_size ||= enum_size
|
73
|
-
end
|
74
|
-
|
75
|
-
def enum_size
|
76
|
-
@enum_size ||= enum.size
|
77
|
-
end
|
78
|
-
|
79
|
-
def fetch(index)
|
80
|
-
enum[index]
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
1
|
+
require 'huge_enumerable'
|
2
|
+
# The simplest form of a HugeEnumerable.
|
3
|
+
# This class can be used for large arrays or anything else that responds to [].
|
4
|
+
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
+
# It only has to be able to return the element mapped to the index given to [].
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# Using HugeCollection directly:
|
9
|
+
#
|
10
|
+
# original_array = ('a'..'z').to_a
|
11
|
+
# collection = HugeCollection.new(original_array)
|
12
|
+
# collection.shuffle!
|
13
|
+
# original_array[0..4] # => ["a", "b", "c", "d", "e"]
|
14
|
+
# collection[0..4] # => ["j", "a", "r", "i", "z"]
|
15
|
+
#
|
16
|
+
#
|
17
|
+
# Subclassing HugeCollection
|
18
|
+
#
|
19
|
+
# class StringNext < HugeCollection
|
20
|
+
#
|
21
|
+
# def initialize(size)
|
22
|
+
# @collection_size = size
|
23
|
+
# super ('a'..'z').to_a
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# private
|
27
|
+
#
|
28
|
+
# def fetch(index)
|
29
|
+
# result = ""
|
30
|
+
# index += 1
|
31
|
+
# while index > 0
|
32
|
+
# index -= 1
|
33
|
+
# result.prepend super(index % 26)
|
34
|
+
# index /= 26
|
35
|
+
# end
|
36
|
+
# result
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# googol = 10*100
|
42
|
+
# collection = StringNext.new(googol)
|
43
|
+
# collection.size # => 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
44
|
+
# collection[0] # => "a"
|
45
|
+
# collection[-1] # => "zhxrtplbmwaiwcqlzpmglpziaegsdivmbvlnssusbjtbcgywaycqnhxztqwwikxvrsptazpp"
|
46
|
+
# collection[googol / 2] # => "dlijhfafxmqxnusmhfpshmdmopvodxfnkfgivwvnejaapyxmynutdlmjhxxqrykiiuizzhi"
|
47
|
+
# collection.shuffle!
|
48
|
+
# collection[0] # => "bipzqqzayczkgsmaseflwktpsotzclcjsqlnnjaciaawufpojywxflknuddhqkilhoedacn"
|
49
|
+
# collection[-1] # => "etneuebyurxgrvrfsreesxuvjaiyoqwplofsptacjdbhuhafdiwbwujvniokltgkjbfkiuy"
|
50
|
+
class HugeCollection < HugeEnumerable
|
51
|
+
|
52
|
+
# Create a new HugeCollection
|
53
|
+
#
|
54
|
+
# ==== Attributes
|
55
|
+
#
|
56
|
+
# * +enumerable+ - Any enumerable that responds to []
|
57
|
+
#
|
58
|
+
# ==== Options
|
59
|
+
#
|
60
|
+
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
61
|
+
# * +:rng+ - The random number generator to use.
|
62
|
+
def initialize(enumerable, max_array_size = nil, rng = nil)
|
63
|
+
@enum = enumerable
|
64
|
+
super(max_array_size, rng)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
attr_accessor :enum
|
70
|
+
|
71
|
+
def collection_size
|
72
|
+
@collection_size ||= enum_size
|
73
|
+
end
|
74
|
+
|
75
|
+
def enum_size
|
76
|
+
@enum_size ||= enum.size
|
77
|
+
end
|
78
|
+
|
79
|
+
def fetch(index)
|
80
|
+
enum[index]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -1,118 +1,112 @@
|
|
1
|
-
require 'huge_enumerable'
|
2
|
-
# HugeCombination is a HugeEnumerable style combination. Comparable to Array#combination.
|
3
|
-
# This class can be used to generate combinations of large arrays or anything else that responds to [].
|
4
|
-
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
-
# It only has to be able to return the element mapped to the index given to [].
|
6
|
-
# ==== Examples
|
7
|
-
#
|
8
|
-
# Using HugeCombination directly:
|
9
|
-
#
|
10
|
-
# combination = HugeCombination.new(('a'..'z').to_a, 2)
|
11
|
-
# combination[0..4] # => [["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["a", "f"]]
|
12
|
-
# combination[23..27] # => [["a", "y"], ["a", "z"], ["b", "c"], ["b", "d"], ["b", "e"]]
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# Subclassing HugeCombination
|
16
|
-
#
|
17
|
-
# class NumberArray < HugeCollection
|
18
|
-
#
|
19
|
-
# def initialize(size)
|
20
|
-
# @collection_size = size
|
21
|
-
# super(nil)
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# private
|
25
|
-
#
|
26
|
-
# def fetch(index)
|
27
|
-
# index
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# class NumberCombination < HugeCombination
|
33
|
-
#
|
34
|
-
# def initialize(size)
|
35
|
-
# enumerable = size < 10 ? (0...size).to_a : NumberArray.new(size)
|
36
|
-
# super enumerable, 2, nil, nil
|
37
|
-
# end
|
38
|
-
#
|
39
|
-
# private
|
40
|
-
#
|
41
|
-
# def fetch(index)
|
42
|
-
# array = super
|
43
|
-
# sum = array.inject(0) { |sum, i| sum += i }
|
44
|
-
# "#{array.first} + #{array.last} = #{sum}"
|
45
|
-
# end
|
46
|
-
#
|
47
|
-
# end
|
48
|
-
#
|
49
|
-
# combination = NumberCombination.new(10**30)
|
50
|
-
# size = combination.size # => 499999999999999999999999999999500000000000000000000000000000
|
51
|
-
# combination[0] # => "0 + 1 = 1"
|
52
|
-
# combination[-1] # => "999999999999999999999999999998 + 999999999999999999999999999999 = 1999999999999999999999999999997"
|
53
|
-
# combination[size / 2] # => "292893218813452475599155637895 + 296085173605458049080913472356 = 588978392418910524680069110251"
|
54
|
-
class HugeCombination < HugeCollection
|
55
|
-
|
56
|
-
# Create a new HugeCombination
|
57
|
-
#
|
58
|
-
# ==== Attributes
|
59
|
-
#
|
60
|
-
# * +enumerable+ - Any enumerable that responds to []
|
61
|
-
# * +size+ - The number of elements per combination to use from enumerable.
|
62
|
-
#
|
63
|
-
# ==== Options
|
64
|
-
#
|
65
|
-
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
66
|
-
# * +:rng+ - The random number generator to use.
|
67
|
-
def initialize(enumerable, size, max_array_size = nil, rng = nil)
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
87
|
-
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
ec = enum_size * c
|
114
|
-
(-c + 2*ec - c**2)/2
|
115
|
-
end
|
116
|
-
|
117
|
-
end
|
118
|
-
|
1
|
+
require 'huge_enumerable'
|
2
|
+
# HugeCombination is a HugeEnumerable style combination. Comparable to Array#combination.
|
3
|
+
# This class can be used to generate combinations of large arrays or anything else that responds to [].
|
4
|
+
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
+
# It only has to be able to return the element mapped to the index given to [].
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# Using HugeCombination directly:
|
9
|
+
#
|
10
|
+
# combination = HugeCombination.new(('a'..'z').to_a, 2)
|
11
|
+
# combination[0..4] # => [["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["a", "f"]]
|
12
|
+
# combination[23..27] # => [["a", "y"], ["a", "z"], ["b", "c"], ["b", "d"], ["b", "e"]]
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# Subclassing HugeCombination
|
16
|
+
#
|
17
|
+
# class NumberArray < HugeCollection
|
18
|
+
#
|
19
|
+
# def initialize(size)
|
20
|
+
# @collection_size = size
|
21
|
+
# super(nil)
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# private
|
25
|
+
#
|
26
|
+
# def fetch(index)
|
27
|
+
# index
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# class NumberCombination < HugeCombination
|
33
|
+
#
|
34
|
+
# def initialize(size)
|
35
|
+
# enumerable = size < 10 ? (0...size).to_a : NumberArray.new(size)
|
36
|
+
# super enumerable, 2, nil, nil
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# private
|
40
|
+
#
|
41
|
+
# def fetch(index)
|
42
|
+
# array = super
|
43
|
+
# sum = array.inject(0) { |sum, i| sum += i }
|
44
|
+
# "#{array.first} + #{array.last} = #{sum}"
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# combination = NumberCombination.new(10**30)
|
50
|
+
# size = combination.size # => 499999999999999999999999999999500000000000000000000000000000
|
51
|
+
# combination[0] # => "0 + 1 = 1"
|
52
|
+
# combination[-1] # => "999999999999999999999999999998 + 999999999999999999999999999999 = 1999999999999999999999999999997"
|
53
|
+
# combination[size / 2] # => "292893218813452475599155637895 + 296085173605458049080913472356 = 588978392418910524680069110251"
|
54
|
+
class HugeCombination < HugeCollection
|
55
|
+
|
56
|
+
# Create a new HugeCombination
|
57
|
+
#
|
58
|
+
# ==== Attributes
|
59
|
+
#
|
60
|
+
# * +enumerable+ - Any enumerable that responds to []
|
61
|
+
# * +size+ - The number of elements per combination to use from enumerable.
|
62
|
+
#
|
63
|
+
# ==== Options
|
64
|
+
#
|
65
|
+
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
66
|
+
# * +:rng+ - The random number generator to use.
|
67
|
+
def initialize(enumerable, size, max_array_size = nil, rng = nil)
|
68
|
+
@combination_size = size
|
69
|
+
super(enumerable, max_array_size, rng)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
attr_reader :combination_size
|
75
|
+
|
76
|
+
def collection_size
|
77
|
+
@collection_size ||= size_of_combination(enum_size, combination_size)
|
78
|
+
end
|
79
|
+
|
80
|
+
def fetch(index)
|
81
|
+
indexes_for(collection_size - index - 1).map { |i| enum[enum_size - i - 1] }
|
82
|
+
end
|
83
|
+
|
84
|
+
def size_of_combination(n, k)
|
85
|
+
k < 0 || n < k ? 0 : factorial(n)/(factorial(k) * factorial(n - k))
|
86
|
+
end
|
87
|
+
|
88
|
+
def indexes_for(position)
|
89
|
+
k = combination_size
|
90
|
+
indexes = []
|
91
|
+
while k > 0
|
92
|
+
n, size = next_n_and_size(position, k)
|
93
|
+
position -= size
|
94
|
+
k -= 1
|
95
|
+
indexes << n
|
96
|
+
end
|
97
|
+
indexes
|
98
|
+
end
|
99
|
+
|
100
|
+
def next_n_and_size(p, k)
|
101
|
+
n = k - 1
|
102
|
+
size = size_of_combination(n, k)
|
103
|
+
begin
|
104
|
+
rc = [n, size]
|
105
|
+
n += 1
|
106
|
+
size = size_of_combination(n, k)
|
107
|
+
end while size <= p
|
108
|
+
rc
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
@@ -1,67 +1,80 @@
|
|
1
|
-
require 'huge_enumerable'
|
2
|
-
# HugePermutation is a HugeEnumerable style permutation. Comparable to Array#permutation.
|
3
|
-
# This class can be used to generate permutations of large arrays or anything else that responds to [].
|
4
|
-
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
-
# It only has to be able to return the element mapped to the index given to [].
|
6
|
-
# ==== Examples
|
7
|
-
#
|
8
|
-
# Using HugePermutation directly:
|
9
|
-
#
|
10
|
-
# permutation = HugePermutation.new(('a'..'z').to_a, 2)
|
11
|
-
# permutation[0..4] # => [["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["a", "f"]]
|
12
|
-
# permutation[23..27] # => [["a", "y"], ["a", "z"], ["b", "a"], ["b", "c"], ["b", "d"]]
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# Subclassing HugePermutation
|
16
|
-
#
|
17
|
-
# class SouthernNames < HugePermutation
|
18
|
-
#
|
19
|
-
# def initialize
|
20
|
-
# base_names = %w{Bill Joe Jo Bob Mary Lou Betty Sue Jimmy Ann Lee Ruby Jack Belle Daisy Dixie Lynn}
|
21
|
-
# super base_names, 2, nil, nil
|
22
|
-
# end
|
23
|
-
#
|
24
|
-
# private
|
25
|
-
#
|
26
|
-
# def fetch(index)
|
27
|
-
# "Your southern name is: #{super(index).join(' ')}"
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# end
|
31
|
-
#
|
32
|
-
# southern_name = SouthernNames.new
|
33
|
-
# southern_name[0] # => "Your southern name is: Bill Joe"
|
34
|
-
# southern_name[-1] # => "Your southern name is: Lynn Dixie"
|
35
|
-
# size = southern_name.size # => 272
|
36
|
-
# southern_name[size / 2] # => "Your southern name is: Jimmy Ann"
|
37
|
-
class HugePermutation < HugeCollection
|
38
|
-
|
39
|
-
# Create a new HugePermutation
|
40
|
-
#
|
41
|
-
# ==== Attributes
|
42
|
-
#
|
43
|
-
# * +enumerable+ - Any enumerable that responds to []
|
44
|
-
# * +size+ - The number of elements per permutation to use from enumerable.
|
45
|
-
#
|
46
|
-
# ==== Options
|
47
|
-
#
|
48
|
-
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
49
|
-
# * +:rng+ - The random number generator to use.
|
50
|
-
def initialize(enumerable,
|
51
|
-
|
52
|
-
super(enumerable, max_array_size, rng)
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def collection_size
|
64
|
-
enum_size
|
65
|
-
end
|
66
|
-
|
67
|
-
|
1
|
+
require 'huge_enumerable'
|
2
|
+
# HugePermutation is a HugeEnumerable style permutation. Comparable to Array#permutation.
|
3
|
+
# This class can be used to generate permutations of large arrays or anything else that responds to [].
|
4
|
+
# It is not necessary for the enumerable to be completely mapped into memory.
|
5
|
+
# It only has to be able to return the element mapped to the index given to [].
|
6
|
+
# ==== Examples
|
7
|
+
#
|
8
|
+
# Using HugePermutation directly:
|
9
|
+
#
|
10
|
+
# permutation = HugePermutation.new(('a'..'z').to_a, 2)
|
11
|
+
# permutation[0..4] # => [["a", "b"], ["a", "c"], ["a", "d"], ["a", "e"], ["a", "f"]]
|
12
|
+
# permutation[23..27] # => [["a", "y"], ["a", "z"], ["b", "a"], ["b", "c"], ["b", "d"]]
|
13
|
+
#
|
14
|
+
#
|
15
|
+
# Subclassing HugePermutation
|
16
|
+
#
|
17
|
+
# class SouthernNames < HugePermutation
|
18
|
+
#
|
19
|
+
# def initialize
|
20
|
+
# base_names = %w{Bill Joe Jo Bob Mary Lou Betty Sue Jimmy Ann Lee Ruby Jack Belle Daisy Dixie Lynn}
|
21
|
+
# super base_names, 2, nil, nil
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# private
|
25
|
+
#
|
26
|
+
# def fetch(index)
|
27
|
+
# "Your southern name is: #{super(index).join(' ')}"
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# southern_name = SouthernNames.new
|
33
|
+
# southern_name[0] # => "Your southern name is: Bill Joe"
|
34
|
+
# southern_name[-1] # => "Your southern name is: Lynn Dixie"
|
35
|
+
# size = southern_name.size # => 272
|
36
|
+
# southern_name[size / 2] # => "Your southern name is: Jimmy Ann"
|
37
|
+
class HugePermutation < HugeCollection
|
38
|
+
|
39
|
+
# Create a new HugePermutation
|
40
|
+
#
|
41
|
+
# ==== Attributes
|
42
|
+
#
|
43
|
+
# * +enumerable+ - Any enumerable that responds to []
|
44
|
+
# * +size+ - The number of elements per permutation to use from enumerable.
|
45
|
+
#
|
46
|
+
# ==== Options
|
47
|
+
#
|
48
|
+
# * +:max_array_size+ - The default size of arrays when #to_a is called.
|
49
|
+
# * +:rng+ - The random number generator to use.
|
50
|
+
def initialize(enumerable, size, max_array_size = nil, rng = nil)
|
51
|
+
@permutation_size = size
|
52
|
+
super(enumerable, max_array_size, rng)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
attr_accessor :permutation_size
|
58
|
+
|
59
|
+
def fetch(x)
|
60
|
+
indexes_for(x).map { |i| enum[i] }
|
61
|
+
end
|
62
|
+
|
63
|
+
def collection_size
|
64
|
+
@collection_size ||= factorial(enum_size) / factorial(enum_size - permutation_size)
|
65
|
+
end
|
66
|
+
|
67
|
+
def indexes_for(position)
|
68
|
+
inversions = []
|
69
|
+
(enum_size-permutation_size+1..enum_size).each do |m|
|
70
|
+
inversions.unshift(position % m)
|
71
|
+
position /= m
|
72
|
+
end
|
73
|
+
|
74
|
+
indexes = []
|
75
|
+
positions = (0..enum_size-1).to_a
|
76
|
+
permutation_size.times { |i| indexes << positions.delete_at(inversions[i]) }
|
77
|
+
indexes
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|