Suppose the arrays were as follows.
x = [12, 24, 36, 54, 72, 96, 108]
y = [12, 9]
We can see that the elements of x
that are divisible by all elements of y
are:
[36, 72, 108]
To obtain this array efficiently we may first convert each element of y
to its prime divisors:
require 'prime'
ypd = y.map { |n| Prime.prime_division(n) }
#=> [[[2, 2], [3, 1]], [[3, 2]]]
See Prime::prime_division
Consider, for example, the prime divisors of 12
. We see that they are given by the array
[[2, 2], [3, 1]]
That simply means that
(2**2)*(3**1) #=> 4*3 #=> 12
We observe that for an element of x
to be divisible by both elements of y
it must be divisible by the single number whose prime divisors are given by
[[2, 2], [3, [1, 2].max]] #=> [[2, 2], [3, 2]]
which is
(2**2)*(3**2) #=> 36
By extension, we can simply combine all the elements of y
into a single number, regardless of the size of y
. That could do that as follows.
h = ypd.each_with_object({}) do |a,h|
a.each do |prime,count|
h.update(prime => count) { |_,o,n| [o,n].max }
end
end
#=> {2=>2, 3=>2}
That single number is therefore:
z = h.reduce(1) { |n,(prime,count)| n*(prime**count) }
#=> 36
Lastly, we can select the elements of interest from x
:
x.select { |n| (n % z).zero? }
#=> [36, 72, 108]