the code
def generate_em(minimum, maximum, list) digits_min = minimum.to_s.size digits_min += 1 if minimum > (list.max.to_s*digits_min).to_i digits_max = maximum.to_s.size digits_max -= 1 if maximum < (list.min.to_s*digits_max).to_i (digits_min..digits_max).each_with_object([]) { |n,arr| arr.concat(list.repeated_permutation(n).to_a.map { |a| a.join.to_i }) }. uniq. select { |n| (minimum..maximum).cover?(n) } end
<strong> Examples
# one
minimum = 1 maximum = 100 list = [1, 2, 3] generate_em(minimum, maximum, list)
# 2
minimum = 78 maximum = 3332 list = [3, 4, 5, 6, 7] generate_em(minimum, maximum, list)
# 3
minimum = 0 maximum = 100 list = [0, 1, 2] generate_em(minimum, maximum, list)
Explanation
Example # 1
The steps for the first example above are as follows.
digits_min = minimum.to_s.size
Increase digits_min
by one if the mimimum
greater than the largest digits_min
from the list
.
digits_min += 1 if minimum > (list.max.to_s*digits_min).to_i digits_min
Decrease digits_max
by one if maximum
less than the smallest digits_max
digits from list
.
digits_max -= 1 if maximum < (list.min.to_s*digits_max).to_i digits_max
We improve efficiency by reducing digits_max
from 3
to 2
c = digits_min..digits_max
We can see the elements that will be generated by this enumerator by calling Enumerable # entries (or Enumerate # to_a ).
d.entries #=> [[1, []], [2, []]] n, arr = d.next #=> [1, []] n #=> 1 arr #=> [] e = list.permutation(n) #=> #<Enumerator: [1, 2, 3]:permutation(2)> f = e.to_a #=> [[1], [2], [3]] arr.concat f #=> [[1], [2], [3]] n, arr = d.next #=> [2, [[1], [2], [3]]] n #=> 2 arr #=> [[1], [2], [3]] e = list.permutation(n) #=> #<Enumerator: [1, 2, 3]:permutation(2)> f = e.to_a #=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]] arr.concat f #=> [[1], [2], [3], [1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
arr
returned by each_with_object
.
g = arr.map { |a| a.join.to_i }
Example # 2
In the second example, two-digit combinations are not created because
78 > (list.max.to_s*2).to_i #=> 78 > 77 => true
and no four-digit combinations are generated because
3332 < (list.min.to_s*4).to_i #=> 3332 < 3333 => true
Example # 3
Without uniq
, the method will return duplicate values:
[0, 1, 2, 0, 1, 2, 10, 11, 12, 20, 21, 22, 0, 1, 2, 10, 11, 12, 20, 21, 22, 100]