Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I've started learning Python 2 days ago and my friends said Project Euler is good to learn. I solved the first 9 Problems and although it was very hard it somehow worked every time. But now im stuck and I dont know why. My answer is just about 100000 off (doesnt seem that much when working with those huge numbers). So if one of you has the time to help me find my fault it would be highly appreciated.
x = 2
z = 0
def is_prime(x):
if x == 2:
return True
for n in range(2, 1415):
if x % n == 0:
return False
return True
while x < 2000000:
if is_prime(x) == True:
z = z + x
x = x + 1
elif x >= 2000000:
break
else:
x = x + 1
print(z)
The problem is the function that verifies that the number is prime.
Here's a working function:
def is_prime(x):
if (x<2):
return False
div = 2
while (div < x):
if (x%div == 0):
return False
div += 1
return True
Edit:
Here's a way faster solution:
x = 2
z = 0
def is_prime2(n):
if n == 2:
return True
if n & 1 == 0:
return False
d= 3
while d * d <= n:
if n % d == 0:
return False
d= d + 2
return True
while x <= 2000000:
if is_prime2(x) == True:
z = z + x
x = x + 1
else:
x = x + 1
print(z)
Your is_prime function is the source of your error, specifically,
for n in range(2, 1415)
This will say that no number below 1415 is prime because, for example, 7 is a prime number but is in the range 2-1414, so 7%7 is 0.
Keeping the same basic formatting, we can rewrite it as such, using math to calculate the square root for each number (which is where the 1415 came from). If you don't want to import math, you can make it range(2,x), but that will have a very long computation time.
def is_prime(x):
if x == 2:
return True
for n in range(2, math.ceil(math.sqrt(x))+1): # +1 is for how python handles ranges
if (x % n) == 0:
return False
return True
You can also clean up your code a little bit like this (keeping the same general format):
for x in range(2, 2000000+1): # again, +1 for how python handles ranges
if is_prime(x): # you don't need == True, the True return makes the if statement True
z += x
print(z)
I can't comment so i have a question... you run the code and what is happening? I copy-paste your code and i couldn't run it. So i have this solution for you if is not running
x = 2
z = 0
def is_prime(x):
if x == 2:
return True
for n in range(2, 1415):
if x % n == 0:
return False
return True
is_prime = is_prime(x)
while x < 2000000:
if is_prime == True:
z = z + x
x = x + 1
elif x >= 2000000:
break
else:
x = x + 1
print(z)
This is only if is not running. As the guys said on your comments be more specific about your problem.
Related
i am new to python and i am currently working on a task for my university. The question is the following:
Given that f(x) = x / 2 if x is even and f(x) = 3*x+1 if x is odd, how do i build a loop that picks a number from a range(5,10000) and sequences it for as long as if it hits 1, it stops. Right now i only accomplished that my loop sorts it in different lists. At least :D
This is my current code:
odd = []
even = []
for num in range (5,10000):
if num % 2 == 0:
even.append(sum)
else:
if num % 2 == 1:
odd.append(sum)
This is famous math problem known as Collatz conjecture to make it simple we will perform the function 2x if x is even and 3x+1 if x is odd till it becomes 1. 1 is the minimum possible value of this sequence.
import random
def collatz_sequence(x):
seq = [x]
if x < 1:
return []
while x > 1:
if x % 2 == 0:
x = x / 2
else:
x = 3 * x + 1
seq.append(x)
return seq
maxLength = -1
maxNum = 1
for num in range(5, 10001):
currseq = collatz_sequence(num)
print(currseq)
currseq_len = len(currseq)
if currseq_len > maxLength:
maxLength = currseq_len
maxNum = num
print(maxNum, maxLength)
When I first starting trying the question, my code would take over a minute to even finish running and give me the answer. I have already tried dynamic programming and storing previous numbers so it doesn't have to run the same number multiple times. I have also tried compacting (n3)+1 and n / 2 into a single line with ((n3)+1) but both of these has only managed to cut my code to 10 seconds. Is there anything else I can try to speed up my code?
def Collatz(n):
dic = {a: 0 for a in range(1,1000000)}
dic[1] = 0
dic[2] = 1
number,length = 1,1
for i in range(3,n,1):
z = i
testlength = 0
loop = "T"
while loop == "T":
if z % 2 == 0:
z = z / 2
testlength += 1
else:
z = ((z*3)+1) / 2
testlength += 2
if z < i:
testlength += dic[z]
loop = "F"
dic[i] = testlength
if testlength > length:
print(i,testlength)
number,length = i,testlength
return number,length
print(Collatz(1000000))
When you calculate the sequence for one input, you find out the sequence length for all the intermediate values. It helps to remember all of these in the dictionary so you never have to calculate a sequence twice of any number < n.
I also started at (n-1)//2, since there's no point testing any number x if 2x is going to be tested later, because 2x will certainly have a longer sequence:
def Collatz(n):
dic = [-1]*n
dic[1] = 0
bestlen = 0
bestval = 1
q=[]
for i in range((n-1)//2,n,1):
q.clear()
z = i
while z >= n or dic[z] < 0:
q.append(z)
if z % 2 == 0:
z = z//2
else:
z = z*3+1
testlen = len(q)+dic[z]
if testlen > bestlen:
bestlen = testlen
bestval = i
print (bestval, bestlen)
for j in range(0,len(q)):
z = q[j]
if z < n:
dic[z] = testlen-j
return bestval, bestlen
print(Collatz(1000000))
Although the answer from Matt Timmermanns is fast, it is not quite as easy to understand as a recursive function. Here is my attempt that is actually faster for n = 10*million and perhaps easier to understand...
f = 10000000
def collatz(n):
if n>=collatz.bounds:
if (n % 4) == 0:
return collatz(n//4)+2
if (n % 2) == 0:
return collatz(n//2)+1
return collatz((3*n+1)//2)+2
if collatz.memory[n]>=0:
return collatz.memory[n]
if (n % 2) == 0:
count = collatz(n//2)+1
else:
count = collatz((3*n+1)//2)+2
collatz.memory[n] = count
return count
collatz.memory = [-1]*f
collatz.memory[1] = 0
collatz.bounds = f
highest = max(collatz(i) for i in range(f//2, f+1))
highest_n = collatz.memory.index(highest)
print(f"collatz({highest_n}) is {highest}")
My results:
$ time /usr/bin/python3 collatz.py
collatz(8400511) is 685
real 0m9.445s
user 0m9.375s
sys 0m0.060s
Compared to
$ time /usr/bin/python3 mattsCollatz.py
(8400511, 685)
real 0m10.672s
user 0m10.599s
sys 0m0.066s
I want to check if number, based on lower and upper bound, has prime divisors only 3 and 5 and number should be multiplication of power of 3 and power of 5. My current solution is this. I want to optimize it, since checking powers with for loops isn't good way in my opinion. Thanks in advance.
def checkNum(x):
for i in range(1,50):
for j in range(1,50):
return x == (3**i) * (5**j)
def printResult(l, r):
for i in range(l,r):
if checkNum(i):
print(i)
Based on comments I think this is the best way:
def checkNum(x):
while x%3==0:
x = x //3
while x%5==0:
x = x//5
return x==1
I want to optimize it, since checking powers with for loops isn't good
way in my opinion.
Over a range of random numbers, we improve its speed by doing:
def checkNum0(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
while x % 15 == 0: # speed up the process
x = x // 15
while x % 5 == 0:
x = x // 5
while x % 3 == 0:
x = x // 3
return x == 1
Or we can use a nested loop and combine both divisions into one:
def checkNum(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
for divisor in (15, 5, 3):
while (quotient_remainder := divmod(x, divisor))[1] == 0:
x = quotient_remainder[0]
return x == 1
I have this pseudocode for a Miller-Rabin primality tester:
function isPrime(n, k=5)
if n < 2 then return False
for p in [2,3,5,7,11,13,17,19,23,29]
if n % p == 0 then return n == p
s, d = 0, n-1
while d % 2 == 0
s, d = s+1, d/2
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
if x == n-1 then next i
return False
return True
But translating that to Python is hard because of the next i statement in the inner for loop, which must break two loops. There is no goto in Python. Other questioners who have asked this question on Stack Overflow have been told to use a local function with a return, or a try/except condition, or an additional boolean flag, but those solutions either don't apply here or would greatly uglify this lovely pseudocode.
What is the Pythonic approach to this problem?
I think the pythonic approach would be try/except, readability would prefer a method or a boolean, but I think that this is solvable by adding a single line:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break #*
if x != n-1: #added line
return False
return True
breaking on the line marked with #* is problematic because it returns false, but if we fix that it's just like "next i".
Another solution, suggested by tobias_k, is to use for/else:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break
else: #added line
return False
return True
return False statement would not be called if the loop was break-ed - only if it was exhausted.
You can use break and continue witn a for: else.
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
# Use 'continue' to go to next i (skip inner loop).
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
# Use 'break' to exit this loop and go to next i
# since this loop is at the end of the i loop.
if x == n-1 then next i
else:
# This is only reached if no `break` occurred
return False
return True
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I used some code taken from Rosetta Code. I renamed a few things but I didn't really change anything.
import random
def is_probable_prime(n, num_trials = 5):
assert n >= 2
if n == 2:
return True
if n % 2 == 0:
return False
s = 0
d = n-1
while True:
quotient, remainder = divmod(d, 2)
if remainder == 1:
break
s += 1
d = quotient
assert(2**s * d == n-1)
def try_composite(a):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2**i * d, n) == n-1:
return False
return True
for i in range(num_trials):
a = random.randrange(2, n)
if try_composite(a):
return False
return True
It pretty closely matches some psuedocode. However, when I test the number
123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901
it returns False. Other (python and java) implementations of Miller-Rabin return True for probable prime. After some testing, try_composite returns True after only 2 rounds! I would really like to know any error, I'm guessing a mis-indent or some feature I don't know about.
In your try_composite function, the for loop should be for i in range(1,s). Do not test the case where i is zero.
EDIT: Also, you are missing a test in your try_composite function. Here is my version of the pseudocode:
def isPrime(n, k=5):
def isComposite(s, d):
x = pow(randrange(2,n-1), d, n)
if x == 1 or x == n-1: return False
for r in range(1, s):
x = pow(x, 2, n)
if x == 1: return True
if x == n-1: return False
return True
if n < 2: return False
for p in [2, 3, 5, 7, 11, 13, 17]:
if n % p == 0: return n == p
s, d = 0, n-1
while d % 2 == 0: s, d = s+1, d/2
for i in range(k):
if isComposite(s, d): return False
return True
It's too bad that Python doesn't allow labels on break or continue statements. Here's pseudocode for a much prettier version of the function:
function isPrime(n, k=5)
if n < 2 then return False
for p in [2,3,5,7,11,13,17,19,23,29]
if n % p == 0 then return n == p
s, d = 0, n-1
while d % 2 == 0
s, d = s+1, d/2
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
if x == n-1 then next i
return False
return True
Notice the two places where the control flow goes to next i. There is no good way to write that in Python. One choice uses an extra boolean variable that can be set and tested to determine when to bypass the rest of the code. The other choice, which I took above, is to write a local function to perform the task. This "loop-and-a-half" idiom is convenient and useful; it was proposed in PEP 3136 and rejected by Guido.