Reputation: 33
What is wrong with my code? When i run the program nothing is printed. I want to print the smallest number that is evenly divisible by all of the numbers from 1 to 20.
found = False
i = 20
while found==False:
c = 0 # c checks if the number is the one im looking for
for x in range(1,21):
if i%x==0:
c = c + 1
if c==20: # if c = 20 then its the number im looking for
print i
found = True
i = i + 1
Upvotes: 2
Views: 20067
Reputation: 1
Simplest Solution using Python:
num = 21
while True:
div = 2
while num%div == 0 and div!=21:
div+=1
if div == 21:
print(num)
break
num+=1
Upvotes: 0
Reputation: 15
if you think carefully the answer is LCM of the numbers from 1 to n. here is the code in C++.
#include <bits/stdc++.h>
#define IOS \
ios_base::sync_with_stdio(false); \
cin.tie(NULL);
#define ll long long int
using namespace std;
ll lcm(int n) {
ll ans = 1;
for (ll i = 1; i <= n; i++)
ans = (ans * i) / (__gcd(ans, i));
return ans;
}
int main() {
int i;
cin >> i;
cout << lcm(i);
return 0;
}
Upvotes: 0
Reputation: 43
So it is Euler's problem #5. I've got that one:
#making loop for range of numbers
def rangeCount(number):
lst = [] #using lists to see divisions
for x in range(1, 21):
svalue = number % x
if svalue == 0:
lst.append(x)
else:
break #Need to break to minimize computation.
return lst
number = 2520 #is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. Minimazing compute
lstpst = [] #list pasted/returned from function
while len(lstpst) < 20:
lstpst = rangeCount(number)
print(f"With {number} we get {lstpst}")
number += 2 #even number must be the answer to the problem. Minimazing compute.
And it is my first post/comment on StackOverflow.
Upvotes: 0
Reputation: 33
I tried this method and it was more easier to understand
i=1
while True:
if i%11==0 and i%12==0 and i%13==0 and i%14==0 and i%15==0 and i%16==0 and i%17==0 and i%18==0 and i%19==0 and i%20==0:
break
else:
i+=1
print(i)
But this can be done in milliseconds by finding the prime factors from 11 to 20 and multiplying them.
Upvotes: 0
Reputation: 4524
Another clean and quick thing in Ruby
def compute_lowest_dividing_number number
for i in 2..(number/2)
return i if number%i == 0
end
number
end
lcm = 1
n = 20
for i in 1..n
# look ahead appraoch
next_number = [i+1, n].min
lcm *= compute_lowest_dividing_number(next_number) if lcm % next_number != 0
end
puts lcm
Upvotes: 0
Reputation: 9331
Brute force:
from itertools import count
for i in count(20):
if all(map(lambda x: i % x == 0, range(1, 21))):
print i
break
Non-brute-force:
from itertools import count, takewhile
def primes(n):
"Generate prime numbers up to n"
seen = list()
for i in xrange(2, n + 1):
if all(map(lambda prime: i % prime, seen)):
seen.append(i)
yield i
def smallest(n):
result = 1
for prime in primes(n):
bprime = max(takewhile(lambda x:x<=n, (prime ** c for c in count(1))))
# we could just take last instead of max()
result *= bprime
return result
print smallest(20)
Upvotes: 5
Reputation: 6387
My take (though I love @ondra solution for its elegancy):
from collections import Counter, defaultdict
def primes(n):
return list(x for x in range(1,n+1)
if all(x%y for y in range(2,x)))
primes_20 = primes(20)
def prime_factors(n):
if n <= 0 or n < 20:
raise ValueError
factors = []
while n > 1:
for x in primes_20[1:]:
if not n % x:
n = n / x
factors.append(x)
break
return factors
max_count = defaultdict(int)
for i in range(2,21):
factors = prime_factors(i)
counts = Counter(factors)
for factor in counts:
max_count[factor] = max(max_count[factor], counts[factor])
total = 1
for factor, count in max_count.items():
total *= factor**count
assert any(total%x for x in range(2)) == False
print total
Upvotes: 0
Reputation: 29081
def is_divisible(n):
for divisor in range(2, 21):
if n % divisor != 0:
return False
return True
number = 1
while not is_divisible(number):
number+=1
print(number)
However, you don't have to check all numbers 1..20. If a number is divisible by 20, it is divisible by 2, 5, 10. Extending this, it would be sufficient to check only divisors from 11..20. Another simple thing would be to increase the candidate solutions by 20 (number += 20
) instead of 1, since any other number would not be divisible by 20.
however, you are essentially looking for the least common multiple of the numbers from 1 to 20, and this can be done using prime factorization: You write each number in [1, 20] as multiple of primes, you take the largest exponential for each prime and then you multiply the results (try it manually to understand it). In this way, the number you are looking for is 2^4 *3^2 * 5 * 7 * 11 * 13 * 17 * 19
Upvotes: 0
Reputation: 31260
Brute forcing this is WAY too slow. You need to find out what the prime factors of each number below 20 are, and then construct the smallest number that includes the same, and it will be the answer.
from collections import Counter
primes_below_20 = [2, 3, 5, 7, 11, 13, 17, 19]
def prime_factors(n):
# Assume n <= 20
if n == 1:
return []
for prime in primes_below_20:
if n % prime == 0:
return [prime] + prime_factors(n / prime)
primes_needed = Counter()
for n in range(2, 21):
primes = Counter(prime_factors(n))
primes_needed = primes_needed | primes # | gives the max of existing values
total = 1
for prime, amount in primes_needed.items():
total *= prime ** amount
print total
Upvotes: 5