Emily Wood
Emily Wood

Reputation: 11

Summing A Defined Previous Loop on Ruby

I am attempting to try and sum an array I have created in Ruby. I'm using an integer (10) as an example, but the code must be able to allow any type of integer to be plugged into it. I must plug in a number, & have Ruby find any #'s from 0 to that plugged in number that are divisible by 3 & 5. Numbers should never repeat in the array. Then I need to have those numbers summed. I have created the loop to find those numbers, but my problem is I cannot figure out how to then sum those numbers in the array after. I have googled so many different options, and none have worked. I am very new at this, but I am trying desperately to figure things out. Any help would be much appreciated, thank you.

Here is my code so far, & I know the summing loop doesn't work, but I am showing how I tried:

Attempt #1:

def sum_multiples(num)
  mult = []
  i = 1
  while i < num
    if i % 3 == 0 || i % 5 == 0
      mult << i
    end
    i += 1
  end
  return mult
end

def summing(array)
  array = mult
  sum = 0
  array.each do |x|
  end
  sum += x
end

puts sum_multiples(10)

Attempt #2:

def sum_multiples(num)
  mult = []
  i = 1
  while i < num
    if i % 3 == 0 || i % 5 == 0
      mult << i
    end
    i += 1
  end
  return mult
end

def summing(array)
  array = mult
  array.each { |a| sum += a }
  return array
end

puts sum_multiples(10)

Upvotes: 1

Views: 80

Answers (3)

Andr&#233;s
Andr&#233;s

Reputation: 143

If I understand well what you are attempting to do, you can do it easy with the next function:

# sum all numbers from 0 to `num` that are divisible by 3 & 5
# then sum and return the result
# @param num [Integer] An unsigned integer greater than 0.
# @return [Integer]

def sum_multiples(num)
  ((0..num).select { |e| (e % 3).zero? && (e % 5).zero? }).sum
end

# we know that all numbers divisible by 3 and 5 are multiples of 15
# so this must print 45

p sum_multiples(30)

Explaining a bit, first we create a range from 0 to the given number, then we filter the numbers that we need, then we sum the resulting array.

Upvotes: 1

Stefan
Stefan

Reputation: 114248

Your sum_multiples method seems to be the one returning numbers that are multiples of 3 and / or 5. It doesn't however sum these numbers, so I would remove that prefix:

def multiples(num)
  # ...
end

You also said "from 0 to that plugged in number" so you should start from 0:

def multiples(num)
  mult = []
  i = 0             # <----- 0, not 1
  while i < num
    if i % 3 == 0 || i % 5 == 0
      mult << i
    end
    i += 1
  end
  return mult
end

Let's give it a try:

multiples(10)
#=> [0, 3, 5, 6, 9]

Looks good. One minor suggestion: the method call multiples(10) looks as if it would return multiples of 10 (which it does not). It never mentions 3 or 5 and I would be quite surprised to get that result if I didn't know its implementation. Maybe a more descriptive name for the method and a keyword argument with an appropriate name could help, e.g. multiples_of_3_and_5(upto: 10). For now however, it's good enough.

Now for part 2:

Then I need to have those numbers summed.

For your summing method, you define an argument array:

def summing(array)
  #
end

When you call the method, you have to pass that argument, e.g.:

summing([1, 2, 3])
#       ^^^^^^^^^
#   passed-in argument

This will automatically set the array variable to the passed value (the array [1, 2, 3]). You don't have to set it yourself:

def summing(array)
  array = mult  # <-- not needed, and in fact "mult" is never defined
  # ...
end

In your loop you increment sum via +=. In order to get this working, sum needs an initial value:

def summing(array)
  sum = 0
  array.each { |a| sum += a }
  # ...
end

The last issue is summing's return value. The method is supposed to calculate the sum of the elements in array. I would expect it to also return the calculated sum:

def summing(array)
  sum = 0
  array.each { |a| sum += a }
  return sum  # <-- not array
end

Let's try it:

summing([1, 2, 3])
#=> 6

summing([10, 20])
#=> 30

To plug both methods together, I'd use variables to store the return values:

numbers = multiples(10)
#=> [0, 3, 5, 6, 9]

sum = summing(numbers)
#=> 23

If you don't need the numbers, you could also write:

sum = summing(multiples(10))
#=> 23

i.e. just replace numbers by the expression you previously assigned to it.


Note that your code isn't very idiomatic. You rarely use while loops in Ruby or explicit counters or explicit return statements.

Here's a more idiomatic implementation using a Range and Enumerable#select to fetch the numbers, and Array#sum for summing:

def multiples(num)
  (0..num).select { |i| i % 3 == 0 || i % 5 == 0 }
end

def summing(array)
  array.sum
end

The summing method is merely a wrapper now, you can just as well call the built-in sum directly:

numbers = multiples(10)
sum     = numbers.sum

or

sum = multiples(10).sum
#=> 23

Upvotes: 0

steenslag
steenslag

Reputation: 80085

In your first attempt you have defined a summing method, but you are not using it - which is a good thing because it does not work at all. The good news is that a arrays do have a sum method, so if you change the line return mult to return mult.sum you'll see some progress.

Upvotes: 0

Related Questions