python Find the sum of all multiples of n below m

1.5k views Asked by At
  • Find the sum of all multiples of n below m
  • Keep in Mind n and m are natural numbers (positive integers) m is
    excluded from the multiples
  • sumMul(2, 9) ==> 2 + 4 + 6 + 8 = 20
  • sumMul(3, 13) ==> 3 + 6 + 9 + 12 = 30
  • sumMul(4, -7) ==> "INVALID"

I did sum of list using range(n, m, n) using n as step. I also tried modulus to avoid range 3 args error.

I can pass many tests but cannot pass all of them.

I have tried lots of logic but to no avail. What I am doing wrong?

CODEWARS: https://www.codewars.com/kata/57241e0f440cd279b5000829/train/python

MY CODE:

def sum_mul(n, m):
    my_list = [number for number in range(n, m) if number % n == 0]
    sum_list = sum(my_list)
    if sum_list >= 1:
        return sum_list
    elif n == 0 and m == 0:
        return 'INVALID'
    elif n == m:
        return n - m
    elif n > m:
        return 'INVALID'
4

There are 4 answers

0
marksman123 On BEST ANSWER

You have one main problem, that is you should prevent the situation when n==0 and you divide it in your list comprehension. It will raise zero division error. so you should check before the validation that n is not equal to zero. Second thing is that you need to check whether n or m are negatives, as the exercise declared both n and m should be positives.

def sum_mul(n, m):
    if n==0:
        return 'INVALID'
    my_list = [number for number in range(n, m) if number % n == 0]
    sum_list = sum(my_list)
    if sum_list >= 1:
        return sum_list
    elif n < 0 and m <= 0:
        return 'INVALID'
    elif n == m:
        return n - m
    elif n > m:
        return 'INVALID'
7
Jose TorrĂ³ On

You should comprove all cases before call sum function.

Like this:

def sum_mul(n, m): 
    if n == 0 or m == 0:
        return 'INVALID'
    if n == m:
        return n - m
    if n<0 or m<0:
        return 'INVALID'
    
    my_list = [number for number in range(n, m) if number % n == 0]
    return sum(my_list)

In fact, you dont't need to create if elif structure because you are using returns, so next instruction after return not executed.

5
tobias_k On

Your code fails if n == 0 as then the number % n checks in the list comprehension fail, so you should check that before trying to compute the sum. Also, you could use a range with step and just do sum(range(n, m, n)). However, both ways might be too slow for some test cases with very large m.

You can do this in O(1) with the following observations:

  1. there are (m-1) // n multiples of n below m
  2. the sum of natural numbers from 1 to n is n*(n+1)//2

Combine those two to get the result.

Example for sumMul(3, 13) ==> 3 + 6 + 9 + 12 = 30:

  • (13-1) // 3 == 4 so we know there are 4 multiples of 3 below 13
    • those are 3 + 6 + 9 + 12 == 3 * (1 + 2 + 3 + 4)
  • with (2) we know 1 + 2 + 3 + 4 == 4*5//2 == 10
  • so the result is 10 * 3 == 30

Putting that into code and handling the special cases is left as an exercise to the interested reader.

0
Alain T. On

You can just compute that result mathematically using integer divisions:

def sum_mul(n, m):
    if n<1 or n>m: return "INVALID"
    return m//n*(m//n+1)//2*n

First you get the number of multiple of n in m (which is merely dividing m by n ignoring the remainder) : m//n

Multiples of n will be nx1, nx2, nx3, ... up to the number of multiples. Factorizing the sum of those by n we get: n(1+2+3+ ... m//n).

The sum of numbers from 1 up to a given number x is obtained by x(x+1)/2. In this case x is the number of multiples m//n

Putting it all together we get n * x * (x+1) /2 where x is m//n, so:

n * (m//n) * (m // n + 1) // 2