coding challenge => You have an array of integers, and for each index you want to find the product of every integer except the integer at that index.
#####That title is a mouthful; say it 5x fast…go. Jk. Below is how I went about solving this Q, written lovingly in Ruby.
Here’s the skinny: we are gonna’ need to write a function/method that takes in an array of integers for the argument and returns an array of the products (those integers multiplied with each other).
What really helps me is knowing what the expected output is going to look like when this method returns from doing its thing. What this question wants is something along these lines:
1
2
3
4
5
6
7
8
9
10
# Imagine this is what we start with
[2, 6, 3, 5]
# This is what the method should return
# Order doesn't matter here, as long as the array
# has these values
[36, 60, 30, 90]
# The method gets there by calculating this
[6*3*5, 2*3*5, 2*6*5, 2*6*3]
Feast them eyes on my solution. Don’t worry if this looks cray cray or confusing, I’ll explain it all the best I can. I also used long and descriptive variable names so others can quickly figure out what’s going on with the code. When I refer to line #’s, use the code snippet below.
1
2
3
4
5
6
7
8
9
def get_product_of_all_ints_except_at_index(start_array)
final_array_of_products = []
num_of_combos_needed = (start_array.length - 1)
all_combos = start_array.combination(num_of_combos_needed).to_a
all_combos.each { |combo| final_array_of_products << combo.reduce(:*) }
final_array_of_products
end
I knew that I was going to have to iterate through the start_array
. But how? Was I going to use Enumerable#each_with_index
? Sounds reasonable. Got me thinking though: I need combinations. That’s the key to this problem.
Does the Array
class have something already baked in to help with combinations? Does the Enumerable
class?
Using Google-Fu, I came across this from the Ruby Documentation: Array#Combination. Like, omg. That’s exactly the type of behavior I want. It even has helpful examples on how to use it: noice!
1
2
3
4
5
6
# From Ruby Docs
a = [1, 2, 3, 4]
a.combination(1).to_a #=> [[1],[2],[3],[4]]
a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
a.combination(4).to_a #=> [[1,2,3,4]]
I know I needed a combination of three (since we’re starting with 4 elements in the array), but what if the initial start_array
has more integer elements inside it besides 4? Wouldn’t it be neat-o if, in the future, we can supply this method with an array of ANY amount of integers AND have it return what we expect?!
1
2
# Boom! Now we'll get just the right amount of combinations
num_of_combos_needed = (start_array.length - 1)
Stepping through the get_product_of_all_ints_except_at_index
method so far, I first declared the variable final_array_of_products
which references an empty array (I’ll use this later). Then line 3
takes the start_array
’s length and subtracts 1 so we will always get the perfect amount of combinations; that value is referenced via the num_of_combos_needed
variable.
On line 4
, the start_array
calls the combination
method, supplies it with the variable num_of_combos_needed
, which works its lovely combo magic, and finally there’s the to_a
call at the end.
What to_a
does is convert the calling object (in our case start_array
) to an array. If we didn’t have that conversion to an array, the return value of the combination
method is an Enumerable object and that just won’t cut the mustard. All of that is then referenced too via the all_combos
variable.
1
2
# 'all_combos' will now reference [[2, 6, 3], [2, 6, 5], [2, 3, 5], [6, 3, 5]]
all_combos = start_array.combination(num_of_combos_needed).to_a
What we have now with the all_combos
variable is 1 outer array with 4 little arrays inside it. On line 6
, I iterate through those 4 little arrays and use Ruby’s helpful Enumerable
method reduce
on each little array.
What does the reduce
method do? Always, always check the ruby documentation. It has everything you need, especially helpful examples.
1
all_combos.each { |combo| final_array_of_products << combo.reduce(:*) }
The above code is saying “Yo, for every little array inside of all_combos
, multiply all the elements into one number via reduce
, and then push that number into the final_array_of_products
array via the <<
(shovel) operator.”
Finally, on line 8
, we have the get_product_of_all_ints_except_at_index
method return final_array_of_products
variable which references that once empty array with 4 numbers inside.
1
2
# This gets returned from the method when the dust settles
final_array_of_products # => [36, 60, 30, 90]
Hope this helps. Stay turnt.