31

I am total newbie to programming and python. I was solving a problem. I found the solution but it seems like too slow.

    if n % 2 == 0 and n % 3 == 0 and\
       n % 4 == 0 and n % 5 == 0 and\
       n % 6 == 0 and n % 7 == 0 and\
       n % 8 == 0 and n % 9 == 0 and\
       n % 10 == 0 and n % 11 == 0 and\
       n % 12 == 0 and n % 13 == 0 and\
       n % 14 == 0 and n % 15 == 0 and\
       n % 16 == 0 and n % 17 == 0 and\
       n % 18 == 0 and n % 19 == 0 and\
       n % 20 == 0:

This is the piece the code to check whether n is divisible by all numbers from 2 to 20 or not.

How I can make it short and efficient.

  • 5
    Do you know about for loops ? – pistache Aug 03 '16 at 11:57
  • @pistache Yes little bit. – Sanatan Chaudhary Aug 03 '16 at 12:02
  • You have many answers. If one solved your problem (e.g. @DeepSpace's answer,) please mark it as Accepted. – eenblam Aug 03 '16 at 18:44
  • Short and efficient are conflicting goals. – edc65 Aug 03 '16 at 19:13
  • 29
    **Please** don't use backslash to continue those lines. They break super easily (just add a space after the backslash and you get a `SyntaxError`). Instead: just wrap the condition in parenthesis: `if (n% 2 == 0 and n % 3 == 0 and n%4 == 0 and n % 5 == 0 and n%6 == 0 ...):` The continuation of the line is implicit. – Bakuriu Aug 03 '16 at 19:26
  • 2
    I couldn't find an exact duplicate, but here are some related questions http://stackoverflow.com/questions/38720150/one-if-statement-with-unknown-number-of-conditions-python/38720186 and http://stackoverflow.com/questions/181530/python-style-multiple-line-conditions-in-ifs – kasravnd Aug 03 '16 at 19:27
  • 8
    You know, you don't need to check *all* those cases.. if `n % 20 ==0` is true, then `n % 2 == 0`, `n % 5 == 0`, `n % 10 ==0` must all be true as well. Maybe think about that, and see how many checks you can eliminate. – Blorgbeard Aug 03 '16 at 21:13
  • @Blorgbeard Yup, you'd only need to check 2, 3, 5, 7, 11, 13, 17 and 19. – Alexander Aug 03 '16 at 22:17
  • 1
    @AlexanderMomchliov, it is actually not just the primes, as they would not account for multiples of squares, like 4. You would actually need to check only the highest necessary squares: **16**, **9**, 5, 7, 11, 13, 17, and 19 in this case – Solomon Ucko Aug 03 '16 at 23:50
  • I'm voting to re-open this question. The OP doesn't want a code review (and this question in its current state would be off-topic for Code Review), they want a more compact / Pythonic way to perform multiple related tests. The `all` / `any` generator expression solutions show how to do that. My answer sees the OP's question as a bit of an XY problem: a little mathematical analysis shows how to achieve the desired result with a single test. – PM 2Ring Aug 04 '16 at 12:00
  • If one of the answers below fixes your issue, you should accept it (click the check mark next to the appropriate answer). That does two things. It lets everyone know your issue has been resolved to your satisfaction, and it gives the person that helps you credit for the assist. See [here](http://meta.stackexchange.com/a/5235) for a full explanation. – PM 2Ring Aug 04 '16 at 12:01
  • 1
    Mathematically, if there's no remainder from modulo 2 there will not be a remainder for any multiple of 2. To check the odd numbers, you could just cancel out the multiples. So, if modulo 5 is zero, no need to check modulo 15, etc. – Alex W Aug 04 '16 at 13:46
  • Related reading: [solutions for Project Euler 5 on CodeReview.SE](http://codereview.stackexchange.com/search?q=euler+5+is%3Aquestion) –  Aug 04 '16 at 14:34
  • @AlexW wait, so you're saying that 20 divides evenly by fifteen, then? I don't see how that works. – This isn't my real name Aug 04 '16 at 15:38
  • @Thisisn'tmyrealname In my last sentence I should've been more verbose: "if modulo 3 == 0 and modulo 5 == 0, no need to check if modulo 15 == 0". Basically, reducing mathematically will improve performance by removing unnecessary checks and shrinking the magnitude of the modulo calculations. – Alex W Aug 04 '16 at 15:54
  • https://projecteuler.net/problem=5 – kadamb Aug 05 '16 at 08:14

11 Answers11

80

There's a trade-off between short and efficient.

The Short way is if all(n % i == 0 for i in range(2, 21)):

The Efficient way is to notice that things like n % 20 == 0 also mean that n % f == 0 where f is any factor of 20. For example, you can drop n % 2 == 0. So you'll end up with fewer comparisons which will run faster. In doing this you'll notice a pattern and you'll notice that the entire statement reduces to if n % 232792560 == 0! But that has now deeply embedded the 20 within it so will be difficult to unpick if you need a different upper limit.

So you see that the efficient way is not so easy to read and maintain. So pick the one best suited to your requirements.

Bathsheba
  • 220,365
  • 33
  • 331
  • 451
  • 7
    Good answer. Could also calculate the LCM and store it, which would help mitigate the unreadable problem and also make the of using 20 less deeply embedded. – xandermonkey Aug 03 '16 at 13:22
  • 4
    Well, use [`primesfrom2to`](https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n) to get primes under `N`. Then raise each to the highest power still less than `N`. Then take their product. Now you can algorithmically produce the `232792560` constant. Memoize if performance requires. – Yakk - Adam Nevraumont Aug 03 '16 at 19:19
  • 4
    How is the short way shorter than the efficient way? – Marc van Leeuwen Aug 03 '16 at 21:55
  • @MarcvanLeeuwen, the efficient way check with fewer numbers, there is no need to check `n % 2` if you already checked `n % 4` as all zero results of the first are already covered by the second. – Surt Aug 03 '16 at 22:47
  • 4
    A quicker version of the ‘short’ way: change the 2 to 11. – Anton Sherwood Aug 04 '16 at 05:40
59

There's a smarter way to do this. If n is divisible by every integer in range(1, 21) then it must be a multiple of the least common multiple of those integers.

You can calculate the LCM of a set of numbers progressively, using the GCD (greatest common divisor). You can import the gcd function from the fractions module, or implement it directly in your code.

def gcd(a, b):
    ''' Greatest Common Divisor '''
    while b:
        a, b = b, a % b
    return a

def lcm(a, b):
    ''' Least Common Multiple '''
    return a * b // gcd(a, b)

# Compute the LCM of range(1, 21)
n = 2
for i in range(3, 21):
    n = lcm(n, i)

lcm20 = n
print('LCM =', lcm20)
#test 
for i in range(1, 21):
    print(i, lcm20 % i)

output

LCM = 232792560
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
20 0

Now, to test if any number n is divisible by all the numbers is range(1, 21) you can just do

n % lcm20 == 0

or hard-code the constant into your script:

# 232792560 is the LCM of 1..20
n % 232792560 == 0

As Anton Sherwood points out in his comment we can speed up the process of finding the required LCM by just taking the LCM of the upper half of the range. This works because each number in the lower half of the range is a divisor of a number in the upper half of the range.

We can improve the speed even further by in-lining the GCD and LCM calculations, rather than calling functions to perform those operations. Python function calls are noticeably slower than C function calls due to the extra overheads involved.

Yakk mentions an alternative approach to finding the required LCM: calculate the product of the prime powers in the range. This is quite fast if the range is large enough (around 40 or so), but for small numbers the simple LCM loop is faster.

Below is some timeit code that compares the speed of these various approaches. This script runs on Python 2 and 3, I've tested it on Python 2.6 and Python 3.6. It uses a prime list function by Robert William Hanks to implement Yakk's suggestion. I've modified Robert's code slightly to make it compatible with Python 3. I suppose there may be a more efficient way to find the prime powers; if so, I'd like to see it. :)

I mentioned earlier that there's a GCD function in the fractions module. I did some time tests with it, but it's noticeably slower than my code. Presumably that's because it does error checking on the arguments.

#!/usr/bin/env python3

''' Least Common Multiple of the numbers in range(1, m)

    Speed tests

    Written by PM 2Ring 2016.08.04
'''


from __future__ import print_function
from timeit import Timer
#from fractions import gcd

def gcd(a, b):
    ''' Greatest Common Divisor '''
    while b:
        a, b = b, a % b
    return a

def lcm(a, b):
    ''' Least Common Multiple '''
    return a * b // gcd(a, b)

def primes(n):
    ''' Returns a list of primes < n '''
    # By Robert William Hanks, from https://stackoverflow.com/a/3035188/4014959
    sieve = [True] * (n//2)
    for i in range(3, int(n ** 0.5) + 1, 2):
        if sieve[i//2]:
            sieve[i*i//2::i] = [False] * ((n - i*i - 1) // (2*i) + 1)
    return [2] + [2*i + 1 for i in range(1, n//2) if sieve[i]]

def lcm_range_PM(m):
    ''' The LCM of range(1, m) '''
    n = 1
    for i in range(2, m):
        n = lcm(n, i)
    return n

def lcm_range_AS(m):
    ''' The LCM of range(1, m) '''
    n = m // 2
    for i in range(n + 1, m):
        n = lcm(n, i)
    return n

def lcm_range_fast(m):
    ''' The LCM of range(1, m) '''
    n = m // 2
    for i in range(n + 1, m):
        a, b = n, i
        while b:
            a, b = b, a % b
        n = n * i // a
    return n

def lcm_range_primes(m):
    n = 1
    for p in primes(m):
        a = p
        while a < m:
            a *= p
        n *= a // p
    return n

funcs = (
    lcm_range_PM,
    lcm_range_AS,
    lcm_range_fast,
    lcm_range_primes
)

def verify(hi):
    ''' Verify that all the functions give the same result '''
    for i in range(2, hi + 1):
        a = [func(i) for func in funcs]
        a0 = a[0]
        assert all(u == a0 for u in a[1:]), (i, a)
    print('ok')

def time_test(loops, reps):
    ''' Print timing stats for all the functions '''
    timings = []
    for func in funcs:
        fname = func.__name__
        setup = 'from __main__ import num, ' + fname
        cmd = fname + '(num)'
        t = Timer(cmd, setup)
        result = t.repeat(reps, loops)
        result.sort()
        timings.append((result, fname))

    timings.sort()
    for result, fname in timings:
        print('{0:16} {1}'.format(fname, result))

verify(500)

reps = 3
loops = 8192
num = 2
for _ in range(10): 
    print('\nnum = {0}, loops = {1}'.format(num, loops))
    time_test(loops, reps)
    num *= 2
    loops //= 2

print('\n' + '- ' * 40)

funcs = (
    lcm_range_fast,
    lcm_range_primes
)

loops = 1000
for num in range(30, 60):
    print('\nnum = {0}, loops = {1}'.format(num, loops))
    time_test(loops, reps)

output

ok

num = 2, loops = 8192
lcm_range_PM     [0.013914467999711633, 0.01393848999941838, 0.023966414999449626]
lcm_range_fast   [0.01656803699916054, 0.016577592001340236, 0.016578077998929075]
lcm_range_AS     [0.01738608899904648, 0.017602848000024096, 0.01770572900022671]
lcm_range_primes [0.0979132459997345, 0.09863009199943917, 0.10133290699923236]

num = 4, loops = 4096
lcm_range_fast   [0.01580070299860381, 0.01581421999981103, 0.016406731001552544]
lcm_range_AS     [0.020135083001150633, 0.021132826999746612, 0.021589830999801052]
lcm_range_PM     [0.02821666900126729, 0.029041511999821523, 0.036708851001094445]
lcm_range_primes [0.06287289499960025, 0.06381634699937422, 0.06406087200048205]

num = 8, loops = 2048
lcm_range_fast   [0.015360695999333984, 0.02138442599971313, 0.02630166100061615]
lcm_range_AS     [0.02104746699842508, 0.021742354998423252, 0.022648989999652258]
lcm_range_PM     [0.03499621999981173, 0.03546843599906424, 0.042924503999529406]
lcm_range_primes [0.03741390599861916, 0.03865244000007806, 0.03959638999913295]

num = 16, loops = 1024
lcm_range_fast   [0.015973221999956877, 0.01600381199932599, 0.01603960700049356]
lcm_range_AS     [0.023003745000096387, 0.023848425998949097, 0.024875303000953863]
lcm_range_primes [0.028887982000014745, 0.029422679001072538, 0.029940758000520873]
lcm_range_PM     [0.03780223299872887, 0.03925949299991771, 0.04462484900068375]

num = 32, loops = 512
lcm_range_fast   [0.018606906000059098, 0.02557359899947187, 0.03725786200084258]
lcm_range_primes [0.021675119000065024, 0.022790905999499955, 0.03934840099827852]
lcm_range_AS     [0.025330593998660333, 0.02545427500081132, 0.026093265998497372]
lcm_range_PM     [0.044320442000753246, 0.044836185001258855, 0.05193238799984101]

num = 64, loops = 256
lcm_range_primes [0.01650579099987226, 0.02443148000020301, 0.033489004999864846]
lcm_range_fast   [0.018367127000601613, 0.019002625000211992, 0.01955779200034158]
lcm_range_AS     [0.026258470001266687, 0.04113643799973943, 0.0436801750001905]
lcm_range_PM     [0.04854909000096086, 0.054864030998942326, 0.0797669980001956]

num = 128, loops = 128
lcm_range_primes [0.013294352000229992, 0.013383581999732996, 0.024317635999977938]
lcm_range_fast   [0.02098568399924261, 0.02108044199849246, 0.03272008299973095]
lcm_range_AS     [0.028861763999884715, 0.0399744570004259, 0.04660961700028565]
lcm_range_PM     [0.05302166500041494, 0.059346372001527925, 0.07757829000001948]

num = 256, loops = 64
lcm_range_primes [0.010487794999789912, 0.010514846000660327, 0.01055656300013652]
lcm_range_fast   [0.02619308099929185, 0.02637610199963092, 0.03755473099954543]
lcm_range_AS     [0.03422451699952944, 0.03513622399987071, 0.05206341099983547]
lcm_range_PM     [0.06851765200008231, 0.073690847000762, 0.07841700100107118]

num = 512, loops = 32
lcm_range_primes [0.009275872000216623, 0.009292663999076467, 0.009309271999882185]
lcm_range_fast   [0.03759837500001595, 0.03774761099884927, 0.0383951439998782]
lcm_range_AS     [0.04527828100071929, 0.046646228000099654, 0.0569303670017689]
lcm_range_PM     [0.11064135100059502, 0.12738902800083451, 0.13843623499997193]

num = 1024, loops = 16
lcm_range_primes [0.009248070000467123, 0.00931658900117327, 0.010279963000357384]
lcm_range_fast   [0.05642254200029129, 0.05663530499987246, 0.05796714499956579]
lcm_range_AS     [0.06509247900066839, 0.0652738099997805, 0.0658949799999391]
lcm_range_PM     [0.11376448099872505, 0.11652833600055601, 0.12083648199950403]

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

num = 30, loops = 1000
lcm_range_fast   [0.03275446999941778, 0.033530079999763984, 0.04002811799909978]
lcm_range_primes [0.04062690899991139, 0.040886697999667376, 0.04130547800014028]

num = 31, loops = 1000
lcm_range_fast   [0.03423191600086284, 0.039976395999474335, 0.04078094900069118]
lcm_range_primes [0.04053011599899037, 0.04140578700025799, 0.04566663300101936]

num = 32, loops = 1000
lcm_range_fast   [0.036124262000157614, 0.036700047998238006, 0.04392546200142533]
lcm_range_primes [0.042666604998885305, 0.04393434200028423, 0.05142524700022477]

num = 33, loops = 1000
lcm_range_fast   [0.03875456000059785, 0.03997290300139866, 0.044469664000644116]
lcm_range_primes [0.04280027899949346, 0.0437891679994209, 0.04381238600035431]

num = 34, loops = 1000
lcm_range_fast   [0.038203157999305404, 0.03937257799952931, 0.04531203700025799]
lcm_range_primes [0.043273317998682614, 0.043349457999283914, 0.04420187600044301]

num = 35, loops = 1000
lcm_range_fast   [0.04228670399970724, 0.04346491300020716, 0.047442203998798504]
lcm_range_primes [0.04332462999991549, 0.0433610400014004, 0.04525857199951133]

num = 36, loops = 1000
lcm_range_fast   [0.04175829099949624, 0.04217126499861479, 0.046840714998324984]
lcm_range_primes [0.04339772299863398, 0.04360795700085873, 0.04453475599984813]

num = 37, loops = 1000
lcm_range_fast   [0.04231068799890636, 0.04373836499871686, 0.05010528200000408]
lcm_range_primes [0.04371378700125206, 0.04463105400100176, 0.04481986299833807]

num = 38, loops = 1000
lcm_range_fast   [0.042841554000915494, 0.043649038998410106, 0.04868016199907288]
lcm_range_primes [0.04571479200058093, 0.04654245399979118, 0.04671720700025617]

num = 39, loops = 1000
lcm_range_fast   [0.04469198100014182, 0.04786454099848925, 0.05639159299971652]
lcm_range_primes [0.04572433999965142, 0.04583652600013011, 0.046649005000290344]

num = 40, loops = 1000
lcm_range_fast   [0.044788433999201516, 0.046223339000789565, 0.05302252199908253]
lcm_range_primes [0.045482261000870494, 0.04680115900009696, 0.046941823999077315]

num = 41, loops = 1000
lcm_range_fast   [0.04650144500010356, 0.04783133000091766, 0.05405569400136301]
lcm_range_primes [0.04678159699869866, 0.046870936999766855, 0.04726529199979268]

num = 42, loops = 1000
lcm_range_fast   [0.04772527699969942, 0.04824955299955036, 0.05483534199993301]
lcm_range_primes [0.0478546140002436, 0.048954233001495595, 0.04905354400034412]

num = 43, loops = 1000
lcm_range_primes [0.047872637000182294, 0.048093739000250935, 0.048502418998396024]
lcm_range_fast   [0.04906317900167778, 0.05292572700091114, 0.09274570399975346]

num = 44, loops = 1000
lcm_range_primes [0.049750300000596326, 0.050272532000235515, 0.05087747600009607]
lcm_range_fast   [0.050906279000628274, 0.05109869400075695, 0.05820328499976313]

num = 45, loops = 1000
lcm_range_primes [0.050158660000306554, 0.050309066000409075, 0.054478109999763547]
lcm_range_fast   [0.05236714599959669, 0.0539534259987704, 0.058996140000090236]

num = 46, loops = 1000
lcm_range_primes [0.049894845999006066, 0.0512076260001777, 0.051318084999365965]
lcm_range_fast   [0.05081920200063905, 0.051397655999608105, 0.05722950699964713]

num = 47, loops = 1000
lcm_range_primes [0.04971165599999949, 0.05024208400027419, 0.051092388999677496]
lcm_range_fast   [0.05388393700013694, 0.05502788499870803, 0.05994341699988581]

num = 48, loops = 1000
lcm_range_primes [0.0517014939996443, 0.05279760400117084, 0.052917389999493025]
lcm_range_fast   [0.05402479099939228, 0.055251746000067214, 0.06128628700025729]

num = 49, loops = 1000
lcm_range_primes [0.05412415899991174, 0.05474224499994307, 0.05610057699959725]
lcm_range_fast   [0.05757830900074623, 0.0590323519991216, 0.06310263200066402]

num = 50, loops = 1000
lcm_range_primes [0.054892387001018506, 0.05504404100065585, 0.05610281799999939]
lcm_range_fast   [0.0588886920013465, 0.0594741389995761, 0.06682244199873821]

num = 51, loops = 1000
lcm_range_primes [0.05582956999933231, 0.055921465000210446, 0.06004790299994056]
lcm_range_fast   [0.060586288000195054, 0.061715600999377784, 0.06733965300009004]

num = 52, loops = 1000
lcm_range_primes [0.0557458109997242, 0.05669860099988, 0.056761407999147195]
lcm_range_fast   [0.060323355999571504, 0.06177857100010442, 0.06778404599936039]

num = 53, loops = 1000
lcm_range_primes [0.05501838899908762, 0.05541463699955784, 0.0561610999993718]
lcm_range_fast   [0.06281833000139159, 0.06334177999997337, 0.06843207200108736]

num = 54, loops = 1000
lcm_range_primes [0.057314272000439814, 0.059501444000488846, 0.060004871998899034]
lcm_range_fast   [0.06634221600143064, 0.06662889200015343, 0.07153233899953193]

num = 55, loops = 1000
lcm_range_primes [0.05790564500057371, 0.05824322199987364, 0.05863306900027965]
lcm_range_fast   [0.06693624800027465, 0.06784769100158883, 0.07562533499913116]

num = 56, loops = 1000
lcm_range_primes [0.057219010001063, 0.05858367799919506, 0.06246676000046136]
lcm_range_fast   [0.06854197999928147, 0.06999059400004626, 0.07505119899906276]

num = 57, loops = 1000
lcm_range_primes [0.05746709300001385, 0.0587476679993415, 0.0606189070003893]
lcm_range_fast   [0.07094627400147147, 0.07241532700027165, 0.07868066799892404]

num = 58, loops = 1000
lcm_range_primes [0.0576490580006066, 0.058481812999161775, 0.05857339500107628]
lcm_range_fast   [0.07127979200049595, 0.07549924399972952, 0.07849203499972646]

num = 59, loops = 1000
lcm_range_primes [0.057503377998727956, 0.058632499998566345, 0.060360438999850885]
lcm_range_fast   [0.07332589399993594, 0.07625177999943844, 0.08087236799838138]

This timing info was generated using Python 3.6 running on a Debian derivative of Linux, on an ancient 2GHz Pentium IV machine.

Community
  • 1
  • 1
PM 2Ring
  • 50,023
  • 5
  • 64
  • 150
  • 2
    A less code-intense way to calculate lcm of all the numbers from 2 to 20 is to find the largest power of each prime in that range. So the product of `5,7,9,11,13,16,17,19`, aka 232792560. Such an independent approach can confirm that you didn't get your algorithm wrong. – Yakk - Adam Nevraumont Aug 03 '16 at 19:15
  • @Yakk Ah, right. FWIW, I _did_ contemplate getting the prime factors of each number in the range and using max to get the highest prime powers needed, but I figured that would be more intensive than my lcd-via-gcd loop. But I _didn't_ think of using a modified sieve to get the prime powers more efficiently until I saw your comment. :) – PM 2Ring Aug 04 '16 at 06:32
  • @Yakk I've implemented your suggestion, but it turns out to be slower for small ranges. But for large ranges, it leaves a simple LCM loop for dead. :) If you know of a more efficient way (that doesn't involve a 3rd party library written in C) of calculating the prime powers in a range please let me know. – PM 2Ring Aug 04 '16 at 11:22
  • @pm2ring memoize! If the calc is done once on a small rsnge, who cares if it is slow. For large range or repeated, faster and/or cached. – Yakk - Adam Nevraumont Aug 04 '16 at 11:28
  • @Yakk Well sure, if I were calculating lots of these lcm_ranges then I'd just pre-build a large enough prime table, if I had a rough idea of the maximum range size, or use an extendable sieve if that wasn't practical. And if I knew that I'd probably need the same lcm_range more than once I'd definitely memoize it (probably using a mutable default arg for the cache, since that's noticeably faster than using an @decorator). – PM 2Ring Aug 04 '16 at 12:57
49
if all(n % i == 0 for i in range(2, 21)):

all accepts an iterable and returns True if all of its elements are evaluated to True, False otherwise. The n % i == 0 for i in range(2, 21) part returns an iterable with 19 True or False values, depending if n is dividable by the corresponding i value.

DeepSpace
  • 65,330
  • 8
  • 79
  • 117
7

Built in all will help.

Return True if all elements of the iterable are true (or if the iterable is empty).

if all(n % i == 0 for i in xrange(2, 21))
Vishnu Upadhyay
  • 4,813
  • 1
  • 11
  • 26
  • You need the negation of this result ``not all(n % i for i in range(2, 21))`` – kasravnd Aug 03 '16 at 12:03
  • @Kasramvd Thanks for suggestion i update my answer accordingly. – Vishnu Upadhyay Aug 03 '16 at 12:06
  • @Kasramvd, your expression means "if n is a multiple of some number in the range", but the OP wants "if n is a multiple of _each_ number in the range" — which is equivalent to `not any(n%i for i in range(11, 21))` – Anton Sherwood Aug 05 '16 at 17:22
4

It's just a mathematical trick, use something like n % "LCM(1,2,...,20) == 0 which could be coded as:

if n % 232792560 == 0:
    #do whatever you want
Masked Man
  • 1,584
  • 1
  • 15
  • 32
4

For variety, the way you could have used a loop for this is

test = True
for modulus in range(2, 21):
    if n % modulus != 0:
        test = False
        break
if test:
    # Do stuff

If you are comfortable with for-else, you can improve the brevity by

for modulus in range(2, 21):
    if n % modulus != 0:
        break
else:
    # Do stuff

although that pattern may be unusual enough that you wouldn't want to use it.

Another option is to write a helper function

def is_divisible_by_integers_up_to(n, bound):
    for modulus in range(2, bound + 1):
        if n % modulus != 0:
            return False
    return True

if is_divisible_by_integers_up_to(n, 20):
    # Do stuff

However, this particular example is simple enough that doing all with a generator expression as described in the other answers is the best way to go.

3

You need a condition that evaluates True when all divisions give a zero remainder. The two solutions so far proposed don't appear to do that. I suspect the condition you need is

if not any(n % i for i in range(2, 21)):
holdenweb
  • 24,217
  • 7
  • 45
  • 67
3

Many of the above code examples are shorter, but (probably) not efficient enough:

n%2 == 0 =>
    n%4 6 8... ==0
n%3 == 0 =>
    n%3 6 9... ==0

We can use only primes to check within the range:

if all(n % i == 0 for i in [2,3,5,7,11,13,17,19])

Furthermore, if n divides all from 2 to 20, it divides the LCM of 2 to 20.

Luke H
  • 67
  • 7
zinking
  • 5,018
  • 4
  • 43
  • 76
2

I'm a very light python user myself, and I didn't know about all. Those solutions are pretty cool (and probably more efficient than the one I'm about to post). But just if you want to see another way to do it, here is another option:

def IsDivUpTo20(n):
   for i in range(2, 21):
      if n % i != 0:
         return False
   return True

And call it like so

if IsDivUpTo20(50):
   #what to do if it is divisible
else:
   #what to do if it isn't
#for the example of 50, it'll be false and jump to the else part, but you can put any number of variable in there

Functionally it is working pretty much the same way 'all' is, but if you aren't used to the fancy syntax and built-ins this one is a bit more intuitive.

*Note: I use Python 3, not Python 2.7 as the question is tagged. I'm pretty sure this works in that version but if not, someone please correct me.

Cody
  • 2,153
  • 2
  • 8
  • 23
2

Similar to previous answers:

import operator
x = 232792560
if reduce(operator.__and__, [x % n == 0 for n in xrange(2, 21, 2)]):
    print("ok")
copper.hat
  • 184
  • 5
  • 14
0

I don't know if answering your own question is good or not.

Since I need to check. if a number is divisible by numbers from 1 to 20 or not. So it gonna take long time to check. But if I could make checklist shorter then it will efficient.

Like, if a number is divisible by 18 then it also should be divisible by 2   3   6 and  9. So based on this I made my checklist:

if all(n % i == 0 for i in [7,11,13,16,17,18,19,20]):

    # some code

And for 14    15 and 12 think like that.

14 : If a number is divisible by both 2 and 7 it must be divisible by 14.

15: So in the case of 15 that if a number is divisible by 20 so it also should be divisible by 5 and if a number is divisible by 18 so it also should be divisible by 3 and if a number is divisible by both 3 and 5 then it must be divisible by 15.

This is more efficient than checking all number and it also ensures that the number is divisible by all number between 1 and 20.

  • Yes, you can do it this way, but it's much faster to do a single `%` operation with the LCM. It takes a tiny bit of time to calculate the LCM (using the code I posted above, it takes under 20 microseconds to calculate the LCM of the numbers under 20 on my old 2GHz machine), and if you need to check that lots of numbers pass the same divisibility test the overhead of calculating the LCM is negligible. – PM 2Ring Sep 12 '16 at 13:38
  • @PM2Ring Sorry, I haven't understood your answer completely earlier. Indeed a great Answer. – Sanatan Chaudhary Sep 12 '16 at 14:56