9

I've recently been working on Project Euler problems in Python. I am fairly new to Python, and still somewhat new as a programmer.

In any case, I've ran into a speed-related issue coding a solution for problem #5. The problem is,

"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"

I've checked around some, and I haven't been able to find anything on this problem pertaining to Python specifically. There were some completed scripts, but I want to avoid looking at other's code in full, if possible, instead wanting to improve my own.

The code I have written runs successfully for the example of 2520 and the range 1 to 10, and should be directly modifiable to work with the question. However, upon running it, I do not get an answer. Presumably, it is a very high number, and the code is not fast enough. Printing the current number being checked seems to support this, reaching several million without getting an answer.

The code, in it's current implementation is as follows:

rangemax = 20
def div_check(n):
    for i in xrange(11,rangemax+1):
        if n % i == 0:
            continue
        else:
            return False
    return True

if __name__ == '__main__':
   num = 2
   while not div_check(num):
       print num
       num += 2
   print num

I have already made a couple changes which I think should help the speed. For one, for a number to be divisible by all numbers 1 to 20, it must be even, as only even numbers are divisible by 2. Hence, I can increment by 2 instead of 1. Also, although I didn't think of it myself, I found someone point out that a number divisible by 11 to 20 is divisible by 1 to 10. (Haven't checked that one, but it seems reasonable)

The code still, however is not fast enough. What optimisations, either programmatic, or mathematics, can I make to make this code run faster?

Thanks in advance to any who can help.

George Osterweil
  • 1,314
  • 2
  • 11
  • 19
  • 6
    Not code-related, but by the same logic you used to notice that the number has to be a multiple of 2, you can also conclude it has to be a multiple of 3,4,...,10, and therefore must be a multiple of the least common multiple of all of those, namely 2520. – David Z Nov 06 '11 at 02:52
  • Thanks, didn't think of that. I'll try to implement code making use of the LCM. For future reference, is this question overly math-oriented, or is it acceptable as a code-related question? – George Osterweil Nov 06 '11 at 02:59
  • 1
    It's broad enough to be both, though I expect that the most beneficial optimizations you can make will be mathematical, not programmatic. Still, Stack Overflow's standards as to what constitutes a programming related question aren't particularly tight, so I suppose it's fine here. – David Z Nov 06 '11 at 03:03
  • Project Euler questions are usually meant to be solved in whatever way you can think of. Some people solve specific questions with math only, other use “brute force” and make the computer calculate until they have a solution. And others apply both, and try to get a smart program. It’s totally up to you to find your own solution that you understand and that seems most naturally for yourself. Often it is also a good practice to retry problems in a different approach to learn new things. – poke Nov 06 '11 at 03:05
  • 10
    For example for this question it is quite easy to use maths knowledge, make a prime factorization and find out that the least common multiple of all those numbers is `232792560 = 2*2*2*2*3*3*5*7*11*13*17*19`. But it depends a lot on the question type to see if manual maths actually works good enough, or a simple program can solve it much faster (or more efficient). – poke Nov 06 '11 at 03:11
  • 2
    @poke: It is much simpler. [Giltheryn SPOILERS!!! You've been warned] See [here](http://stackoverflow.com/questions/147515/least-common-multiple-for-3-or-more-numbers/147539#147539). – jfs Nov 06 '11 at 03:15
  • I think part of it is I don't exactly have a propensity for math, making some of the problems quite difficult on that front. It's supposed to be challenging, though, and I plan to keep trying to find the best balance between math and programming, despite my relative lack of skill in the former. Hopefully by working on these I'll be able to improve in both of the key areas. As for this problem, I think I'll try to avoid spoilers for a bit longer, and try to go the LCM route. – George Osterweil Nov 06 '11 at 03:16
  • @J.F.Sebastian I think doing a prime factorization is much easier than running a full agorithm 19 times plus some integer divisions though – when you are not using tools. – poke Nov 06 '11 at 03:19
  • @Giltheryn Well, be prepared that the later problems will require you to re-learn quite a few mathematical things though. It doesn’t get easier. But as I said, try the way it is most comfortable for yourself first, and then see if you can improve it :) – poke Nov 06 '11 at 03:20
  • @poke: It takes 12.5 microseconds to find the answer for the numbers from 1 to 20 on my machine. So it is efficient enough in this case. `/` is an integer division if operands are integers in Python 2 if there is no `from __future__ import division`. – jfs Nov 06 '11 at 03:29
  • @J.F.Sebastian: But to be fair, it takes 0.1 microseconds to multiply `2*2*2*2*3*3*5*7*11*13*17*19` :-P – David Z Nov 06 '11 at 05:04
  • @J.F.Sebastian What didn’t you understand about “not using tools”? I explained quite well in my comments that there are different methods to find solutions, and this problem works quite well for doing it by applying maths. – poke Nov 06 '11 at 14:30

21 Answers21

23

Taking the advice of Michael Mior and poke, I wrote a solution. I tried to use a few tricks to make it fast.

Since we need a relatively short list of numbers tested, then we can pre-build the list of numbers rather than repeatedly calling xrange() or range().

Also, while it would work to just put the numbers [1, 2, 3, ..., 20] in the list, we can think a little bit, and pull numbers out:

Just take the 1 out. Every integer is evenly divisible by 1.

If we leave the 20 in, there is no need to leave the 2 in. Any integer evenly divisible by 20 is evenly divisible by 2 (but the reverse might not be true). So we leave the 20 and take out the 2, the 4, and the 5. Leave the 19, as it's prime. Leave the 18, but now we can take out the 3 and the 6. If you repeat this process, you wind up with a much shorter list of numbers to try.

We start at 20 and step numbers by 20, as Michael Mior suggested. We use a generator expression inside of all(), as poke suggested.

Instead of a while loop, I used a for loop with xrange(); I think this is slightly faster.

The result:

check_list = [11, 13, 14, 16, 17, 18, 19, 20]

def find_solution(step):
    for num in xrange(step, 999999999, step):
        if all(num % n == 0 for n in check_list):
            return num
    return None

if __name__ == '__main__':
    solution = find_solution(20)
    if solution is None:
        print "No answer found"
    else:
        print "found an answer:", solution

On my computer, this finds an answer in under nine seconds.

EDIT: And, if we take advice from David Zaslavsky, we realize we can start the loop at 2520, and step by 2520. If I do that, then on my computer I get the correct answer in about a tenth of a second.

I made find_solution() take an argument. Try calling find_solution(2520).

steveha
  • 67,444
  • 18
  • 86
  • 112
  • It occurs to me that we could write Python code to generate a list of numbers `[2, 3, 4, 5, ..., N]` and then loop over it and pull out all the non-needed numbers. Then we could multiply together all the numbers pulled out to get our starting value and step value. And that is just a few changes away from the most elegant solution, which is to just find the minimum set of prime factors and multiply them all together. – steveha Nov 06 '11 at 08:07
  • Oh, you can't just multiply all the numbers pulled out; that list includes 2, 4, 6, 8, 10, etc. The final answer is too large, because it has more factors of 2 than it should; and so on. It's a common multiple but not the *least* common multiple. – steveha Nov 06 '11 at 09:01
  • Quite, helpful, thanks. Implementing much of this logic results in finding the solution in a matter of seconds, rather than over 10 minutes previously. – George Osterweil Nov 06 '11 at 14:40
  • Upon fully implementing this, the code completed in under a second. I didn't measure the exact runtime, but it was by far fast enough. – George Osterweil Nov 06 '11 at 14:57
  • It seems to me that this code returns '20' as the answer rather than the actual solution, have I gone wrong somewhere or did other people get similar answers? – KRS-fun Feb 13 '14 at 13:33
  • I just copied the code, saved it as a Python script, and ran it. I did not get 20 as the answer, I got the correct answer. – steveha Feb 13 '14 at 21:56
8

My first answer sped up the original calculation from the question.

Here's another answer that solves it a different way: just find all the prime factors of each number, then multiply them together to go straight to the answer. In other words, this automates the process recommended by poke in a comment.

It finishes in a fraction of a second. I don't think there is a faster way to do this.

I did a Google search on "find prime factors Python" and found this:

http://www.stealthcopter.com/blog/2009/11/python-factors-of-a-number/

From that I found a link to factor.py (written by Mike Hansen) with some useful functions:

https://gist.github.com/weakish/986782#file-factor-py

His functions didn't do quite what I wanted, so I wrote a new one but used his pull_prime_factors() to do the hard work. The result was find_prime_factors() which returns a list of tuples: a prime number, and a count. For example, find_prime_factors(400) returns [(2,4), (5,2)] because the prime factors of 400 are: (2*2*2*2)*(5*5)

Then I use a simple defaultdict() to keep track of how many we have seen so far of each prime factor.

Finally, a loop multiplies everything together.

from collections import defaultdict
from factor import pull_off_factors

pf = defaultdict(int)

_primes = [2,3,5,7,11,13,17,19,23,29]
def find_prime_factors(n):
    lst = []
    for p in _primes:
        n = pull_off_factors(n, p, lst)
    return lst

def find_solution(low, high):
    for num in xrange(low, high+1):
        lst = find_prime_factors(num)
        for n, count in lst:
            pf[n] = max(pf[n], count)

    print "prime factors:", pf
    solution = 1
    for n, count in pf.items():
        solution *= n**count

    return solution

if __name__ == '__main__':
    solution = find_solution(1, 20)
    print "answer:", solution

EDIT: Oh wow, I just took a look at @J.F. Sebastian's answer to a related question. His answer does essentially the same thing as the above code, only far more simply and elegantly. And it is in fact faster than the above code.

Least common multiple for 3 or more numbers

I'll leave the above up, because I think the functions might have other uses in Project Euler. But here's the J.F. Sebastian solution:

def gcd(a, b):
    """Return greatest common divisor using Euclid's Algorithm."""
    while b:
        a, b = b, a % b
    return a

def lcm(a, b):
    """Return lowest common multiple."""
    return a * b // gcd(a, b)

def lcmm(*args):
    """Return lcm of args."""   
    return reduce(lcm, args)

def lcm_seq(seq):
    """Return lcm of sequence."""
    return reduce(lcm, seq)

solution = lcm_seq(xrange(1,21))
print "lcm_seq():", solution

I added lcm_seq() but you could also call:

lcmm(*range(1, 21))
steveha
  • 67,444
  • 18
  • 86
  • 112
  • The link to factor.py is dead. Can you post it here if you still have it? – Keatinge Apr 16 '17 at 10:15
  • @Keatinge The gist link worked for me when I tried it: https://gist.github.com/weakish/986782#file-factor-py The blog posting that pointed me to the gist does appear to be dead. – steveha Mar 22 '20 at 08:30
6

Since your answer must be divisible by 20, you can start at 20 and increment by 20 instead of by two. In general, you can start at rangemax and increment by rangemax. This reduces the number of times div_check is called by an order of magnitude.

Michael Mior
  • 26,133
  • 8
  • 80
  • 110
2

I got the solution in 0.066 milliseconds (only 74 spins through a loop) using the following procedure:

Start with smallest multiple for 1, which = 1. Then find the smallest multiple for the next_number_up. Do this by adding the previous smallest multiple to itself (smallest_multiple = smallest_multiple + prev_prod) until next_number_up % smallest_multiple == 0. At this point smallest_multiple is the correct smallest multiple for next_number_up. Then increment next_number_up and repeat until you reach the desired smallest_multiple (in this case 20 times). I believe this finds the solution in roughly n*log(n) time (though, given the way numbers seem to work, it seems to complete much faster than that usually).

For example:

1 is the smallest multiple for 1

Find smallest multiple for 2

Check if previous smallest multiple works 1/2 = .5, so no

previous smallest multiple + previous smallest multiple == 2.

Check if 2 is divisible by 2 - yes, so 2 is the smallest multiple for 2

Find smallest multiple for 3

Check if previous smallest multiple works 2/3 = .667, so no

previous smallest multiple + previous smallest multiple == 4

Check if 4 is divisible by 3 - no

4 + previous smallest multiple == 6

Check if 6 is divisible by 3 - yes, so 6 is the smallest multiple for 3

Find smallest multiple for 4

Check if previous smallest multiple works 6/4 = 1.5, so no

previous smallest multiple + previous smallest multiple == 12

Check if 12 is divisble by 4 - yes, so 12 is the smallest multiple for 4

repeat until 20..

Below is code in ruby implementing this approach:

def smallestMultiple(top)
    prod = 1
    counter = 0
    top.times do
        counter += 1
        prevprod = prod
        while prod % counter != 0
            prod = prod + prevprod
        end
    end
    return prod
end
TheSneak
  • 429
  • 6
  • 14
2

Break down the number as a prime factorization.

All primes less than 20 are:

2,3,5,7,11,13,17,19

So the bare minimum number that can be divided by these numbers is:

2*3*5*7*11*13*17*19

Composites:

4,6,8,9,10,12,14,15,16,18,20 = 2^2, 2*3, 2^3, 3^2, 2*5, 2^2*3, 2*7, 3*5, 2*3^2, 2^2*5

Starting from the left to see which factors needed:

  • 2^3 to build 4, 8, and 16
  • 3 to build 9
  • Prime factorization: 2^4 * 3^2 * 5 * 7 * 11 * 13 * 17 * 19 = 232,792,560
admdrew
  • 3,600
  • 4
  • 22
  • 39
UhOhs
  • 39
  • 1
  • This is exactly the sort of thinking Project Euler is supposed to inspire. The first few problems only require mathematical thinking not programming. – Pete Kirkham Jul 08 '16 at 10:45
  • This made sense. I applied the concept to my solution the response time went from ~7 seconds to ~2 milliseconds in Java. I do not understand why this isn't the accepted answer. – Dorado May 21 '20 at 19:03
1

Two different types of solutions have been posted here. One type uses gcd calculations; the other uses prime factorization. I'll propose a third type, which is based on the prime factorization approach, but is likely to be much faster than prime factorization itself. It relies on a few simple observations about prime powers -- prime numbers raised to some integral exponent. In short, it turns out that the least common multiple of all numbers below some number n is equal to the product of all maximal prime powers below n.

To prove this, we begin by thinking about the properties that x, the least common multiple of all numbers below n, must have, and expressing them in terms of prime powers.

  1. x must be a multiple of all prime powers below n. This is obvious; say n = 20. 2, 2 * 2, 2 * 2 * 2, and 2 * 2 * 2 * 2 are all below 20, so they all must divide x. Likewise, 3 and 3 * 3 are both below n and so both must divide x.

  2. If some number a is a multiple of the prime power p ** e, and p ** e is the maximal power of p below n, then a is also a multiple of all smaller prime powers of p. This is also quite obvious; if a == p * p * p, then a == (p * p) * p.

  3. By the unique factorization theorem, any number m can be expressed as a multiple of prime powers less than m. If m is less than n, then m can be expressed as a multiple of prime powers less than n.

Taken together, the second two observations show that any number x that is a multiple of all maximal prime powers below n must be a common multiple of all numbers below n. By (2), if x is a multiple of all maximal prime powers below n, it is also a multiple of all prime powers below n. So by (3), it is also a multiple of all other numbers below n, since they can all be expressed as multiples of prime powers below n.

Finally, given (1), we can prove that x is also the least common multiple of all numbers below n, because any number less than x could not be a multiple of all maximal prime powers below n, and so could not satisfy (1).

The upshot of all this is that we don't need to factorize anything. We can just generate primes less than n!

Given a nicely optimized sieve of eratosthenes, one can do that very quickly for n below one million. Then all you have to do is find the maximal prime power below n for each prime, and multiply them together.

prime_powers = [get_max_prime_power(p, n) for p in sieve(n)]
result = reduce(operator.mul, prime_powers)

I'll leave writing get_max_prime_power as an exercise. A fast version, combined with the above, can generate the lcm of all numbers below 200000 in 3 seconds on my machine.

The result is a 86871-digit number!

Community
  • 1
  • 1
senderle
  • 125,265
  • 32
  • 201
  • 223
  • @steveha, I think you were on the right track with your prime factorization approach; see the above for another optimization that (on my machine) results in much faster code than any of the `gcd`-based code here, at least for large values. – senderle Jul 15 '12 at 16:31
1

This solution ran pretty quickly for me (imports numpy).

t0 = time.time()
import numpy

ints = numpy.array(range(1,21))
primes = [2,3,5,7,11,13,17,19] # under 20
facts = []
for p in primes:
    counter = 0
    nums = ints
    while any(nums % p == 0):
        nums = nums / float(p)
        counter += 1
    facts.append(counter)

facts = numpy.array(facts)
mults = primes**facts
ans = 1
for m in mults:
    ans = m * ans

t1 =time.time()
perf = t1 - t0
print "Problem 5\nAnswer:",ans, "runtime:", perf, "seconds"

"""Problem 5
Answer: 232792560 runtime: 0.00505399703979 seconds"""
jlemaitre
  • 426
  • 4
  • 14
1

I wrote a solution to euler5 that:

  • Is orders of magnitude faster than most of the solutions here when n=20 (though not all respondents report their time) because it uses no imports (other than to measure time for this answer) and only basic data structures in python.
  • Scales much better than most other solutions. It will give the answer for n=20 in 6e-05 seconds, or for n=100 in 1 millisec, faster than most of the responses for n=20 listed here.

    import time
    a=time.clock() # set timer
    
    j=1
    factorlist=[]
    mydict={}
    # change second number to desired number +1 if the question were changed.
    for i in range(2,21,1):
        numberfactors=[]
        num=i
        j=2
    # build a list of the prime factors
        for j in range(j,num+1,1):
            counter=0
            if i%j==0:
                while i%j==0:
                    counter+=1
                    numberfactors.append(j)
                    i=i/j
    # add a list of factors to a dictionary, with each prime factor as a key
                    if j not in mydict:
                        mydict[j] = counter
    # now, if a factor is already present n times, including n times the factor
    # won't increase the LCM. So replace the dictionary key with the max number of
    # unique factors if and only if the number of times it appears is greater than
    # the number of times it has already appeared.
    # for example, the prime factors of 8 are 2,2, and 2. This would be replaced 
    # in the dictionary once 16 were found (prime factors 2,2,2, and 2).
                elif mydict[j] < counter:
                    mydict[j]=counter
    
    total=1
    for key, value in mydict.iteritems():
        key=int(key)
        value=int(value)
        total=total*(key**value)
    
    b=time.clock()
    elapsed_time=b-a
    print total, "calculated in", elapsed_time, "seconds"
    

    returns:

    232792560 calculated in 6e-05 seconds
    
    # does not rely on heuristics unknown to all users, for instance the idea that 
    # we only need to include numbers above 10, etc.
    
    
    # For all numbers evenly divisible by 1 through 100:
    69720375229712477164533808935312303556800 calculated in 0.001335 seconds
    
Vincent Laufer
  • 631
  • 7
  • 25
1

List comprehensions are faster than for loops.

Do something like this to check a number:

def get_divs(n):
    divs = [x for x in range(1,20) if n % x == 0]
    return divs

You can then check the length of the divs array to see if all the numbers are present.

khill
  • 569
  • 4
  • 5
  • 1
    Then you can also simply do `return all( n % x == 0 for x in range(1,21) )` – note the upper range `21` to include the `20` in the checks. – poke Nov 06 '11 at 03:17
  • I've not gotten in to list comprehensions yet, but it's easy enough to find out. I'll check that out, thanks. – George Osterweil Nov 06 '11 at 03:21
  • Glitheryn, the solution by khill is a list comprehension solution, which generates a list. The solution by poke is a "generator expression" solution, which is similar to a listcomp but doesn't build the whole list; it yields numbers one at a time, which gives a speed advantage. A listcomp must build a list; if you didn't want the list, but just the numbers, then the list gets used once and then gets taken apart again. The overhead of building up and tearing down the list can be avoided by the genexp. – steveha Nov 06 '11 at 07:32
0

Here is program in C language. Cheers

#include <stdio.h>
#include <stdlib.h>
//2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
//What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
bez_ost(int q)
{
    register br=0;
    for( register i=1;i<=20;i++)
    if(q%i==0)
    br++;

    if(br==20)
    return 1;
    return 0;
}

int main()
{
   register j=20;
   register ind=0;

   while(ind!=1)
   {
       j++;
       if(bez_ost(j))
       break;
   }
   fprintf(stdout,"\nSmallest positive number that is evenlu divisible by all of the numbers from 1 to 20 is: %d\n\a",j);
   system("Pause");

}
Nick
  • 31
  • 1
0

I've had the same problem. The algorithm seems to be quite slow, but it does work nonetheless.

result = list()
xyz = [x for x in range(11, 21)]
number = [2520]
count = 0
while len(result) == 0:
    for n in number:
        print n
        for x in xyz:
            if n % x == 0:
                count += 1
            elif n % x != 0:
                count = 0
                break
    if count == 10:
        result.append(number[0])
    elif count != 10:
        number[0] += 1

print result 

This was the algorithm I made.

0

How about this? The required number is, after all, the LCM of the given numbers.

def lcm(a,b):
lcm1 = 0
if a == b:
    lcm1 = a
else:
    if a > b:
        greater = a
    else:
        greater = b
    while True:
        if greater % a == 0 and greater % b == 0:
            lcm1 = greater
            break
        greater += 1

return lcm1            


import time
start_time = time.time()

list_numbers = list(range(2,21))

lcm1 = lcm(list_numbers[0],list_numbers[1])

for i in range(2,len(list_numbers)):
    lcm1 = lcm(lcm1,list_numbers[i])

print(lcm1)
print('%0.5f'%(time.time()-start_time))

This code took a full 45 s to get the answer to the actual question! Hope it helps.

don_Gunner94
  • 144
  • 11
0
import time
primes = [11,13,17,19]
composites = [12,14,15,16,18,20]

def evenlyDivisible(target):
    evenly = True
    for n in composites:
        if target % n > 0:
            evenly = False
            break
return evenly

step = 1
for p in primes:
    step *= p

end = False
number = 0
t1 = time.time()
while not end:
    number += step
    if evenlyDivisible(number):
        end = True
        print("Smallest positive evenly divisible number is",number)
t2 = time.time()
print("Time taken =",t2-t1)

Executed in 0.06 seconds

Andy7788
  • 1
  • 1
0

Here i have also done using prime factorization way.

#!/usr/bin/env python
import math
def is_prime(num):
    if num > 1:
        if num == 2:
            return True
        if num%2 == 0:
            return False
        for i in range(3, int(math.sqrt(num))+1, 2):
            if num%i == 0:
                return False
        return True
    return False

def lcm(number):
    prime = []
    lcm_value = 1
    for i in range(2,number+1):
        if is_prime(i):
            prime.append(i)
    final_value = []
    for i in prime:
        x = 1
        while i**x < number:
            x = x + 1
        final_value.append(i**(x-1))
    for j in final_value:
        lcm_value = j * lcm_value
    return lcm_value

if __name__ == '__main__':
    print lcm(20)

After checking how much time it has taken, it was not bad at all.

root@l-g6z6152:~/learn/project_euler# time python lcm.py

232792560

real    0m0.019s
user    0m0.008s
sys 0m0.004s
Vikash Singh
  • 671
  • 7
  • 11
0

Here is my Python solution, it has 12 iteration so compiled quite fast:

smallest_num = 1
for i in range (1,21):
    if smallest_num % i > 0: # If the number is not divisible by i
        for k in range (1,21):
            if (smallest_num * k) % i == 0: # Find the smallest number divisible by i    
                smallest_num = smallest_num * k
                break
print (smallest_num)
0

Here's an observation on this problem. Ultimately, it takes 48 iterations to find the solution.

Any number that is divisible by all of the numbers from 1..20 must be divisible by the product of the primes in that range, namely 2, 3, 5, 7, 11, 13, 17, and 19. It cannot be smaller than the product of these primes, so let's use that number, 232,792,560, as the increment, rather than 20, or 2,520, or some other number.

As it turns out, 48 * 232,792,560 is divisible by all numbers 1..20. By the way, the product of all of the non-primes between 1..20 is 66. I haven't quite figured out the relationship between 48 and 66 in this context.

NPHighview
  • 15
  • 1
0
up = int(input('Upper limit: '))
number = list(range(1, up + 1))
n = 1

for i in range(1, up):
    n = n * number[i]
    for j in range(i):
        if number[i] % number[j] == 0:
            n = n / number[j]
            number[i] = number[i] / number[j]
print(n)
  • Please explain how your answer is optimized – alamoot May 07 '18 at 00:48
  • For example, factors of 4 are 2, 2. However, 2 has already been multiplied, if we multiply 4 to n, the result will be 2 times the right answer. We do need to keep the second factor 2 because 2 only shows one time, thus it can't be divided multiple times. – Shixin Xu May 07 '18 at 15:34
0

How I can reduce the complexity of this

num = 1
found = False
while not found:
    count =0
    for i in range(1, 21):
        if num %i == 0:
            count+=1
    if count ==10:
        print(num)
        found = True
    num+=1
vishwaraj
  • 439
  • 4
  • 5
0

Here is the code in C++ to find the solution for this question.

What we have to do is to run a loop from 1 until we got that number so just iterate through the loop and once the number get evenly divisble(remainder 0) flag value dont get change and flag remains 1 and we got that number and break through outer loop and print the answer

    #include <bits/stdc++.h>
using namespace std;

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    int i,j,flag=1;
    for(i=1;;i++)                   //iterate until we got the number
    {
    flag=1;                 
    for(j=2;j<=20;j++)         //check form 1 to 20 for that number
    {
        if(i%j!=0)             //if the number is not evenly divisible we break loop and 
        {
            flag=0;break;         // initilize flag as 0 i.e. that number is not what we want
        }
        
    }
    if(flag==1)                     //if any number we got that is evenly divisible i.e. flag value doesnt change we got that number we break through the loop and print the answer
    break;
    } // after ending of the loop as we jump to next number make flag also 1 again so that again inner loop conditions apply on it
    cout<<i;
    return 0;
}
-1

A typescript variant that seems to be relatively quick, leveraging recursion and known facts.

describe(`2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?`,
() => {
  it("prooves the example: 10", () => smallestWithoutRemainder(10).should.be.equal(2520));
  it("prooves 1", () => smallestWithoutRemainder(1).should.be.equal(1));
  it("prooves 2", () => smallestWithoutRemainder(2).should.be.equal(2));
  it("prooves 3", () => smallestWithoutRemainder(3).should.be.equal(6));
  it("prooves 4", () => smallestWithoutRemainder(4).should.be.equal(12));
  it("prooves 5", () => smallestWithoutRemainder(5).should.be.equal(60));
  it("prooves 6", () => smallestWithoutRemainder(6).should.be.equal(60));
  it("prooves 7", () => smallestWithoutRemainder(7).should.be.equal(420));
  it("prooves 8", () => smallestWithoutRemainder(8).should.be.equal(840));
  it("prooves 9", () => smallestWithoutRemainder(9).should.be.equal(2520));
  it("prooves 12", () => smallestWithoutRemainder(12).should.be.equal(27720));
  it("prooves 20", () => smallestWithoutRemainder(20).should.be.equal(232792560));
  it("prooves 30", () => smallestWithoutRemainder(30).should.be.equal(2329089562800));
  it("prooves 40", () => smallestWithoutRemainder(40).should.be.equal(5342931457063200));
});

let smallestWithoutRemainder = (end: number, interval?: number) => {
  // What do we know?
  // - at 10, the answer is 2520
  // - can't be smaller than the lower multiple of 10
  // - must be an interval of the lower multiple of 10
  // so:
  // - the interval and the start should at least be divisable by 'end'
  // - we can recurse and build on the results before it.
  if (!interval) interval = end;
  let count = Math.floor(end / 10);
  if (count == 1) interval = 2520;
  else if (count > 1) interval = smallestWithoutRemainder((count - 1) * 10, interval);

  for (let i = interval; true; i += interval) {
    let failed = false;
    for (let j = end; j > 1; j--) {
      if (i % j != 0) {
        failed = true;
        break;
      }
    }
    if (!failed) return i;
  }
}
Sickboy
  • 341
  • 3
  • 6
-1

I think this the answer:

primes = [11, 13, 17, 19]
result = 2520

for i in primes:
    result *= i

print (result * 2)
ᴀʀᴍᴀɴ
  • 3,931
  • 7
  • 32
  • 52