Again im stuck on a problem..
I wanted to create a function that puts out all prim factors of a given number.
It was pretty much finished but it wouldnt put out correct factors for numbers which have the same prim factor more than once, for example: 20 - 5, 2, 2
So i added a while loop which checked if the product of all factors equals the number i put in.
Thanks for any help :)
prime_numbers = []
def prime_gen(upper_limit):
for i in range(2, upper_limit):
for j in range(2, i):
if i % j == 0:
break
else:
prime_numbers.append(i)
return prime_numbers
def list_product(list):
sum = 1
for i in list:
sum *= i
return sum
prime_factors = []
def prime_factor(number):
while list_product(prime_factors) != number: #without the while it checked every factor only once
for i in reversed(prime_gen(number)):
while number % i != 0:
break
else:
if i != 1:
number /= i
prime_factors.append(i)
continue
else:
break
prime_factor(20)
print (prime_factors)
Just use a for loop, getting you list of primes from prime_gen:
def prime_gen(upper_limit):
prime_numbers = [2]
for i in range(3, upper_limit,2):
for j in range(2, i):
if i % j == 0:
break
else:
prime_numbers.append(i)
return prime_numbers
def prime_factors(n):
p_f = []
for prime in prime_gen(n):
# while n is divisible keep adding the prime
while n % prime == 0:
p_f.append(prime)
# update n by dividing by the prime
n //= prime
if n > 1:
p_f.append(n)
return p_f
print(prime_factors(40))
[2, 2, 2, 5] # -> 2*2*2*5
If you take 40 as an example:
(40, 2) # first prime 2, 40 is divisible by 2
(20, 2) # 40 //= 2 == 20, 20 is divisible by 2
(10, 2) # 20 //= 2 == 10, 10 is divisible by 2
(5, 5) # 10 //=2 == 5, 5 is not evenly divisible by 2 or 3 so we get 5
If you want a fast way to generate the primes, you can use a sieve:
from math import sqrt
def sieve_of_eratosthenes(n):
primes = range(3, n + 1, 2) # primes above 2 must be odd so start at three and increase by 2
for base in xrange(len(primes)):
if primes[base] is None:
continue
if primes[base] >= sqrt(n): # stop at sqrt of n
break
for i in xrange(base + (base + 1) * primes[base], len(primes), primes[base]):
primes[i] = None
primes.insert(0,2)
sieve=filter(None, primes)
return sieve
The error you are getting (TypeError: 'float' object cannot be interpreted as an integer) is ultimately caused by this statement:
number /= i
In Python 3, the result of /= is always a float. To perform integer division (so that number remains an integer), use:
number //= i
After fixing this, you'll find that you have a logic error that causes an infinite loop.
Related
I need to create a program that takes user input n and the finds the first n numbers that aren't divisible by any other prime numbers except 2, 3, and 5. This is what I've got so far:
def is_divisible(i):
for k in range(7, i):
if is_prime(k) == 1 and i % k == 0:
return 1
else:
return 0
def is_prime(k):
for j in range(2, k):
if k % j == 0:
return 0
else:
return 1
while True:
while True:
while True:
try:
n = input("How many numbers do you want to find: ")
n = n.replace(" ", "")
n = int(n)
break
except:
print("Input only natural numbers")
continue
if n == 0:
print("Input only natural numbers")
continue
else:
break
count = 0
i = 0
while count < n:
if i % 2 == 0 and i % 3 == 0 and i % 5 == 0 and is_divisible(i) == 0:
print(i)
count += 1
i += 1
else:
i += 1
repeat = input("To repeat press (1), to end press anything else: ")
if str(repeat) == "1":
continue
else:
print("Bye!")
break
If asked to find 10 numbers the program outputs:
30
60
90
120
150
180
240
270
300
330
The program didn't print 210 (which is divisible by 7) so the algorithm seems, at least, partly correct, but 330 is printed (which is divisible by 11) and I can't figure out why. If I manually change i to 330 and k to 11, the is_prime function correctly finds that 11 is a prime number, but the is_divisible function still returns 0. I can't figure out what's wrong. Any help will be greatly appreciated!
Thanks!
First, you need to fix your is_prime like #Barmar mentions above
Note, this can be optimized in multiple ways, the simplest of which is to only check for j in range(2, int(math.sqrt(k))+1) because a number k won't have any prime factors greater than sqrt(k). Also, we can memorize all the prime numbers found so far, so that if the same number is checked multiple times, subsequent checks are much faster. You can use better algorithms to check if a number is prime, but this should suffice for our purposes.
import math
# A set to remember prime numbers
primes = set()
def is_prime(k):
if k == 1: return False # 1 is not prime
if k in primes: return True # Check remembered prime numbers
# Check all numbers in the closed interval [2, sqrt(k)]
for j in range(2, int(math.sqrt(k))+1):
if k % j == 0:
return False
# Prime number, so remember it
primes.add(k)
return True
The first n numbers that aren't divisible by any prime numbers other than 2, 3, and 5
Since your number needs to be divisible by 2, 3, and 5, you don't need to look at all numbers as you do currently. Just look at multiples of 2 * 3 * 5, i.e. multiples of 30, since those are the only numbers that are going to be multiples of 2, 3, and 5.
So now your problem becomes: "Print 30 * i, where i is not a multiple of a prime number other than 2, 3, and 5. i.e., you need to get the prime factors of i, and check that this set contains only 2, 3, and 5.
There are a number of ways to get the prime factors of a number. Here's a simple one:
def prime_factors(k):
# If k is prime, it is its only prime factor
if is_prime(k):
return {k}
factors = set()
# If divisible by 2, add 2 as a prime factor
if k % 2 == 0:
factors.add(2)
# Check all odd numbers in the closed interval [3, k//2]
for i in range(3, k//2+1, 2):
if k % i == 0 and is_prime(i):
factors.add(i)
return factors
Now that we've defined our helper functions, we just need to call them:
n = 10
i = 1
count = 0
while count < n:
factors = prime_factors(i)
# If we remove {2, 3, 5} from factors, do we get an empty set?
if not factors.difference({2, 3, 5}):
print(2 * 3 * 5 * i)
count += 1
i += 1
Which prints:
30
60
90
120
150
180
240
270
300
360
If you are indeed looking for regular numbers as #Mark and #Kelly suggest in their comments, then you simply skip the multiplication by 2 * 3 * 5:
n = 10
i = 1
count = 0
while count < n:
factors = prime_factors(i)
# If we remove {2, 3, 5} from factors, do we get an empty set?
if not factors.difference({2, 3, 5}):
print(i)
count += 1
i += 1
gives:
1
2
3
4
5
6
8
9
10
12
Here's a bit of code that looks for values that have other factors besides 2,3,5. If there are other factors in there, they must be other prime values because we remove the prime factors 2,3,5 from the number.
primes = [ 2, 3, 5]
count = 10
answers = []
value = 2
while len(answers) < count:
test_value = value
for prime in primes:
while test_value % prime == 0:
test_value //= prime
if test_value == 1:
answers.append(value)
value += 1
print(answers)
Ok, the performance discussion from #Kelly Bundy bothered me - so I added a different approach - but it's got problems.
import sys
primes = [ 2, 3, 5]
count = int(sys.argv[1])
base = round( count ** (1./3.) )
powers = [0] * len(primes)
answers = []
while True:
value = 1
for n in range(len(primes)):
value *= primes[n] ** powers[n]
answers.append(value)
for n in range(len(powers)):
powers[n] += 1
if powers[n] != base:
break
powers[n] = 0
else:
break
for x in sorted(answers):
print(x)
Basically, all of the numbers we want to find are of the form: 2**x * 3**y * 5**z . And so, if we just vary x,y,and z, we can compute all of the qualifying numbers.
The the problem boils down to, which values of x,y, and z are valid. To be honest, I haven't figured that out. All I do is come up with count combinations of x,y,z where I just count values (using some base counting system). For instance, if I need to come up with 1,000 combinations, I just produce all of the combinations of x,y,z where the values are between 0 and 9. And so i get the values (000 - 999). And this produces the values: 2**0 * 3**0 * 5**0 all the way up to 2**9 * 3**9 * 5**9. Now, I'm definitely missing some values. The 1,000 numbers I come up with are NOT the first 1,000 numbers.
Your is_divisible method basically only checks 7 and then returns either 1 or 0.
You want to check all the numbers in the range.
def is_divisible(i):
for k in range(7, i):
if is_prime(k) == 1 and i % k == 0:
return 1
return 0
Your is_prime method suffers from this issue as well:
def is_prime(k):
for j in range(2, k):
if k % j == 0:
return 0
return 1
Fixing these issues, however, is going make this algorithm EXTREMELY slow so you will need to consider some strategies that will make it faster.
Caching the numbers that you have already checked for primeness would be a start.
I am trying to write a code in python to find all prime numbers of a number. My problem is that with this line of code it does not work to return the prime numbers of 10, the list only returns 2. Now I adapted this code from this page https://www.geeksforgeeks.org/prime-factor/ as I want to make my factors come out as a list.
The code from that website works for the number 10, however I do not understand why it does not work for number 10 when I run my own slightly modified version of it.
I have tried to +10 at the end of my range function, instead of a +1 and this does solve the problem, however I am still unsure as to why I even have a problem in the first place. Secondly, will the +10 work for all numbers with no error? In theory it should as I should only have factors unto square root of n, but I am not sure again. Lastly, if if the +10 does work, won't that make the code run slower as it will iterate through unneeded loops, how can I improve the speed?
This is my code that I used.
import math
def primefact():
n = int(input('What is your number?:'))
prime_factors = []
while n % 2 == 0: # Checks if number is divisible by 2
prime_factors.append(2) #repeats it until n is no longer divisible by 2
n = n / 2
for i in range(3, int(math.sqrt(n)) + 1, 2): # Testing for odd factors
while n % i == 0:
prime_factors.append(i)
n = n / i
print(prime_factors)
return
primefact()
Here's a piece of code that I wrote:
from numpy import mod, int0, sqrt, add, multiply, subtract, greater, equal, less, not_equal, floor_divide
class findFactors:
def __init__(self, n):
self.primeFactorize(n)
def primeFactorize(self, n):
factors = self.findFactors(n)
self.factors = factors
primeFactors = []
xprimeFactors = []
for factor in factors:
if prime(factor).isPrime:
primeFactors.append(factor)
ntf = n
nprime = 0
while not_equal(ntf, 1):
while equal(mod(ntf, primeFactors[nprime]), 0):
ntf = floor_divide(ntf, primeFactors[nprime])
xprimeFactors.append(primeFactors[nprime])
nprime = add(nprime, 1)
self.primeFactors = primeFactors
self.extendedPrimeFactors = xprimeFactors
def findFactors(self, number):
if prime(number).isPrime: return [1, number]
factors = []
s = int0(sqrt(float(number)))
for v in range(1, add(s, 1)):
if equal(mod(number, v), 0):
factors.append(int(v))
factors.append(int(floor_divide(number, v)))
factors.sort()
return factors
class prime:
def __init__(self, n):
self.isPrime = self.verify(n)
def verify(self, n):
if less(n, 2):
return False
if less(n, 4):
return True
if not n & 1 or equal(mod(n, 3), 0):
return False
s = int0(sqrt(float(n)))
for k in range(1, add(s, 1)):
mul = multiply(6, k)
p = add(mul, 1)
m = subtract(mul, 1)
if greater(m, s):
return True
if equal(mod(n, p), 0) or equal(mod(n, m), 0):
return False
Imagine func = findFactors(n)
func.factors will returns a list with all the factors of the number n,
func.extendedPrimeFactors will return a list with the prime factorization of the number,
func.primeFactors will return a list with the primes appearing only once instead of x times
also, there's a really fast prime checker down there.
(Prime checker usage:
prime(n).isPrime
)
Hi you just forgot the last part of the equation
Condition if n is a prime
# number greater than 2
if n > 2:
print n
Here Is the list of all factorial prime numbers, is not the same as prime numbers
https://en.m.wikipedia.org/wiki/Table_of_prime_factors
Here's my code for printing the sum of prime divisors of each number between 18 to 25. But it is only printing 5.
For example:
18 has prime factors 2, 3 hence sum = 5,
19 is prime, hence sum of factors = 0,
20 has prime factors 2 and 5, hence sum = 7,
21 has prime factors 3 and 7, hence sum = 10,
22 has prime factors 2 and 11, hence sum = 13,
23 is prime. hence sum = 0,
24 has prime factors 2 and 3, hence sum = 5,
25 has prime factor 5, hence sum = 5
Therefore, it should print [5,0,7,10,13,0,5,5]
I believe I should use break statement but i tried it didn't work. As I am beginner in python, any kind of help much appreciated.
def isPrime(n):
i = 2
while i * i <= n:
# n has a factor, hence not a prime
if (n % i == 0):
return False
i += 1
# we reach here if n has no factors
# and hence n is a prime number
return True
def summ(l, r):
summ = 0
arrayofdivisors = []
arrayofsum = []
# iterate from lower to upper
for i in range(l, r + 1) :
# if i is prime, it has no factors
if (isPrime(i)) :
continue
for j in range(2, i):
# check if j is a prime factor of i
if (i % j == 0 and isPrime(j)) :
arrayofdivisors.append(j)
if(len(arrayofdivisors)>1):
ans = sum(arrayofdivisors)
arrayofsum.append(ans)
return arrayofsum
# Driver code
if __name__ == "__main__":
l = 18
r = 25
print(summ(l, r))
Try this
def isPrime(n) :
if (n <= 1) :
return False
if (n <= 3) :
return True
if (n % 2 == 0 or n % 3 == 0) :
return False
i = 5
while(i * i <= n) :
if (n % i == 0 or n % (i + 2) == 0) :
return False
i = i + 6
return True
def Sum(N):
SumOfPrimeDivisors = [0] * (N + 1)
for i in range(2, N + 1) :
if (SumOfPrimeDivisors[i] == 0) :
for j in range(i, N + 1, i) :
SumOfPrimeDivisors[j] += i
return SumOfPrimeDivisors[N]
arr=[]
for i in range(18,26):
if isPrime(i):
arr.append(0)
else:
arr.append(Sum(i))
print(arr)
It's almost impossible to tell because of the way you've formatted things, but the problem here is that your "return" statement is indented one position too far. Thus, you return at the end of the first loop, before it has a chance to check anything else. Un-indent the return arrayofsum and it should work.
Then, you are initializing arrayofdivisors outside the main loop, so it just kept getting larger and larger. Then, you weren't adding 0 to the list for prime numbers, as your spec required.
Note that if statements in Python do not need parentheses, like they do in C.
def isPrime(n):
i = 2
while i * i <= n:
# n has a factor, hence not a prime
if n % i == 0:
print(n,'not prime')
return False
i += 1
# we reach here if n has no factors
# and hence n is a prime number
print(n,"prime")
return True
def summ(l, r):
# iterate from lower to upper
arrayofsum = []
for i in range(l, r + 1) :
arrayofdivisors = []
# if i is prime, it has no factors
if isPrime(i):
arrayofsum.append(0)
continue
for j in range(2, i):
# check if j is a prime factor of i
if i % j == 0 and isPrime(j):
arrayofdivisors.append(j)
arrayofsum.append( sum(arrayofdivisors) )
return arrayofsum
# Driver code
if __name__ == "__main__":
l = 18
r = 25
print(summ(l, r))
I am struggling to determine how to get an answer for the following problem.
What I am attempting to do is take x in a list of numbers (eg 1 to 2,000,000) and divide by a certain range of numbers, y, for example 1 to 20 and return my x value only if it is divisible by all the numbers in the second list.
I have tried the following but when I check the list I am trying to append to it returns a blank
divisibles = []
def isdivisible(x):
for i in range(1,21):
if x%i!=0:
return False
return True
for x in range(1,2000001):
if isdivisible(x):
divisibles.append(x)
Please could someone help me.
I am generally struggling with testing for an all case in general.
Thanks.
I believe this might be because no number from 1 to 2000000 is divisible by all numbers from 1 to 20.
Try calculating the LCM for those numbers first.
Your code is fine, but the result is indeed an empty list. There are several primes in range(1, 21):
2, 3, 5, 7, 11, 13, 17, 19
So, the number that will pass your check must be divisible by all of them, so it'll be at least the product of these primes:
>>> 2*3*5*7*11*13*17*19
9,699,690
You're checking up to 2 million, which isn't nearly enough.
Think that it is not possible to find a number in this range that satisfies this function because there are prime numbers such as 1,2,3,5,7 that can only be divided between them and 1. So maybe this function works, but no number fits this divisible range.
First: to check if a number is divisible by all numbers from 1 to 20 you don't need to test all dividers, it is enough to test their Least Common Multiple, which in this case is 232792560. Second: this number is greater than 2000000, so there aren't any numbers in 1 to 2000000 range satisfying your condition.
Optimized solution:
primes = []
temporary_dividor_check = []
max_nominator_divisible = []
max_div = 1
min_denominator = 1
max_denominator = 21
min_nominator = 1
max_nominator = 20000000
counter = 1
nominators = list(range(min_nominator,max_nominator+1))
denominators = range(min_denominator,max_denominator+1)
def generate_prime_numbers(start,end):
global primes
for val in range(start, end + 1):
if val > 1:
for n in range(2, val//2 + 2):
if (val % n) == 0:
break
else:
if n == val//2 + 1:
primes.append(val)
generate_prime_numbers(min_denominator,max_denominator+1)
for prime in primes:
max_div = max_div*prime
while counter * max_div < max_nominator:
max_nominator_divisible.append(counter*max_div)
counter += 1
for divisible1 in max_nominator_divisible:
if divisible1 % max_div == 0:
for denominator in denominators:
divisible = divisible % denominator
if divisible == 0:
temporary_dividor_check.append(denominator)
if temporary_dividor_check == list(denominators):
print("{} is divisible by all denominators".format(divisible1))
temporary_dividor_check = []
The simplest but super CPU-hungry (wasteful)
nominators = range(1,20000000)
denominators = range(1,21)
temporary_dividor_check = []
for nominator in nominators:
for denominator in denominators:
divisible = nominator%denominator
if divisible == 0:
temporary_dividor_check.append(denominator)
if temporary_dividor_check == list(denominators):
print("{} is divisible by all denominators".format(nominator))
temporary_dividor_check = []
I m trying to solver Problem 5 in projecteuler.The problem is as follows
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 have written a simple python program
primes = [2,3,5,7,11,13,17,19]
prod = 1
#function returns the list of prime factors of 'n'
def find_pf(n):
pf = []
for j in primes:
if i % j == 0:
pf.append(j)
return pf
#multiplies all the prime factors of all the numbers
#from 1[1..20]
for i in range(1,21):
lst = find_pf(i)
for i in lst:
prod *= i
#verifies that 'n' is diviible evenly by [1..20]
count = 0
def test_n(n):
global count
for i in range(1,21):
if n % i != 0:
count += 1
print ('smallest number divisible by [1..20] {}'.format(prod))
test_n(prod)
print('Total failures {}'.format(count))
The result obtained by the above program is
smallest number divisible by [1..20] 1055947052160000
Total failures 0
The answer 1055947052160000 is incorrect.? Can someone kindly point out what is wrong with the above program? Or suggest the correct method to solve this problem?
The error is in
#multiplies all the prime factors of all the numbers
#from 1[1..20]
for i in range(1,21):
lst = find_pf(i)
for i in lst:
prod *= i
You are only interested in the highest necessary power of any prime.
For example, the value you are looking for shall be divisible by 16. Your code looks for a number divisible by 2*4*8*16.
Your code is looking for too many primes. It is enough to look for the greatest: e.g. if the number is dividable by 16, it is already dividable by 8.
primes = [2,3,5,7,11,13,17,19]
prod = 1
for p in primes:
n = 2
prod *= p
while (p**n < 21):
prod *= p
n += 1
print prod
Here you get
232792560
def lcm(*values):
values = [value for value in values]
if values:
n = max(values)
m = n
values.remove(n)
while any(n % value for value in values):
n += m
return n
return 0
reduce(lcm, range(1, 20))
In [3]: reduce(lcm, range(1, 20))
Out[3]: 232792560
reduce applies " function of two arguments cumulatively to the items of iterable from left to right, so as to reduce the iterable to a single value."
def add_nums(a,b):
print a,b # added print to show values
return a+b
reduce(add_nums, [1, 2, 3, 4, 5]) #calculates ((((1+2)+3)+4)+5)