It appears you are given:
def test_sum_of_factorials
sum_of_factorials = 0
numbers = [1, 2, 3, 4, 5]
<...missing bits...>
assert_equal 153, sum_of_factorials
end
and are being asked to fill in the missing bits. I think something like the following is being asked for.
def test_sum_of_factorials
sum_of_factorials = 0
numbers = [1, 2, 3, 4, 5]
fac = 1
numbers.each do |n|
fac *= n
sum_of_factorials += fac
end
assert_equal 153, sum_of_factorials
end
We can instead write that as:
def test_sum_of_factorials
numbers = [1, 2, 3, 4, 5]
assert_equal 153, sum_of_factorials(numbers)
end
def sum_of_factorials(numbers)
fac_sum = 0
fac = 1
numbers.each do |n|
fac *= n
fac_sum += fac
end
fac_sum
end
where
sum_of_factorials([1,2,3,4,5])
#=> 153
It would be more Ruby-like, however, to use Array#sum to write sum_of_factorials
as follows:
def sum_of_factorials(numbers)
fac = 1
numbers.sum { |n| fac *= n }
end
Together with the title of your question, this is why the authors of other answers assume you are asking how the method sum_of_factorials
can be improved. Firstly, it can be passed the argument numbers.max
, rather than the array numbers
.
Another way to write sum_of_factorials
is to make use of the method Enumerator::produce, which made its debut in v2.7.
def sum_of_factorials(n)
enum = Enumerator.produce([1,1]) { |n0, n1| [n0+1, (n0+1)*n1] }
n.times.sum { enum.next.last }
end
(1..8).each { |n| puts "%d: %6d" % [n, sum_of_factorials(n)] }
1: 1
2: 3
3: 9
4: 33
5: 153
6: 873
7: 5913
8: 46233
Note that if:
enum = Enumerator.produce([1,1]) { |n0, n1| [n0+1, (n0+1)*n1] }
#=> #<Enumerator: #<Enumerator::Producer:0x000059d490c742a0>:each>
then
enum.next #=> [1, 1]
enum.next #=> [2, 2]
enum.next #=> [3, 6]
enum.next #=> [4, 24]
so the factorials of 1
through 4
are given by (after redefining or rewinding enum
):
enum.next.last #=> 1
enum.next.last #=> 2
enum.next.last #=> 6
enum.next.last #=> 24
If n
could equal zero add the line return 1 if n.zero?
at the beginning of the method.