Why doesn't my answer to project euler 3 work? - python

I've been trying to solve project Euler problem #3 for a while now. The code below still doesn't work the way I want it to.
Question 3: The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
getal = 13195
x = 2
while x in xrange(2,getal):
if getal % x == 0:
num = getal / x
for i in xrange (2,num):
if num % i == 0:
x += 1
break
else:
print num
else:
x += 1
continue
As you can see I'm running it right now with 13195 for the sake of simplicity, but eventually it should have to work with the bigger number.
My output is this:
2639 2639 2639 2639 2639 1885 1885 1885 1015 1015 1015 455 455 455 377
377 377 377 377 377 377 377 377 377 377 203 203 203 203 203 145 145
145 91 91 91 91 91 65 65 65 35 35 35 29 29 29 29 29 29 29 29 29 29 29
29 29 29 29 29 29 29 29 29 29 29 29 29 29
29 goes on for a while longer than I showed.
I do understand it just prints the number as soon as it has found an "i" that this number cannot be divided by. But I don't know how to prevent it from doing this. Because in the end 29 is the right answer, however it should just give this answer once and right away.

You can simplify your code to the code snippet below. It uses a list to store any candidates and then removes them if they are not prime numbers:
import math
getal = 600851475143
x = 2
candidates = [];
while (x < int(math.sqrt(getal)+1)):
if getal % x == 0:
candidates.append(x)
for i in xrange (2,int(math.sqrt(x)+1)):
if x % i == 0:
candidates.remove(x)
break
x = x + 1
print str(candidates).strip('[]')

You need to break out of your while when you find the answer.

You are not incrementing 'x' after print num statement.
for i in xrange (2,num):
if num % i == 0:
break
else:
print num
x += 1
you should be able to even getrid of second if statement as below
getal = 13195
x = 2
while x in xrange(2,getal):
if getal % x == 0:
num = getal / x
for i in xrange (2,num):
if num % i == 0:
break
else:
print num
x += 1

The Answer is 6857. You don't have to check from 2 to the number. Use the property of primes.Check only up-to the square root of the number that you are checking.You can use my Java Code for reference.
class p3{
public static boolean isprime(long y){
double sq = Math.sqrt(y);
long endl =(long) (sq+.5);
for(long j = 2;j <=endl ;j++)
{
if(y%j==0){
return false;
}
}
return true;
}
public static void main(String []asd){
long test = 600851475143L;
long ans =-1;
double e = Math.sqrt(test);
long end = (long)(e+1);
for(long i = 2 ; i <= end ;i++)
{
if(test%i==0){
boolean val = isprime(i);
if(val){
ans = i;
}
}
}
System.out.println(ans);
}
}
If you need any help. I have solved the problems in Project Euler and have saved them in my github repository. You are more than welcome to fork it.The url is:
https://github.com/vatsarahul999/ProjectEuler-.git
Writing the same code in python.
def isprime(n):
if n < 2:
return False
if n == 2:
return True
if not n & 1:
return False
for x in range(3, int(n**0.5)+1, 2):
if n % x == 0:
return False
return True
Now the main program
v = 13195
x = 2
while(x*x <= v)
if(isprime(x)):
a = x
while(v%x==0)
v=v/x;
x++
print a

Here's a sample (it can be improved in terms of performance):
import math
getal = 600851475143
def prime(number):
for i in xrange(2, int(math.sqrt(number)) + 1):
if (number % i) == 0:
return False
return True
def prime_factors(number):
ret = []
n = number
primes = []
for i in [item for item in xrange(2, int(math.sqrt(n)) + 1)]:
if prime(i):
primes.append(i)
for i in primes:
while n % i == 0:
ret.append(i)
n = n / i
return ret
print prime_factors(getal)

Why is everyone incrementing to find the largest number? Decrease!!!
def largestPrime(num):
from __future__ import division
for i in xrange(num//2 + 1, 1, -1):
if num%i == 0 and all([i%j != 0 for j in range(2,i//2 + 1)]):
return i

you are over complicating, to get all factors
getal = 13195
for x in range(2, getal):
if getal % x == 0:
print x
this one should use the for loop not a while,
to use a while here it would be like this
getal = 13195
x = 2
while x < getal:
if getal % x == 0:
print x
x += 1
you dont need to loop thru the constraints to do the work at the loop level - because you are doing it inside

you are actually very close to getting the right answer, you just need to remove indentation in your else statement to have a for else block:
>>> x = 2
>>> getal = 13195
>>> while x in range(2,getal):
if getal % x == 0:
num = getal // x
for i in range (2,num):
if num % i == 0:
x += 1
break #this will break for loop
else:#this is the only change, moving the else from an else inside of the for to a for else block
print (num)
break this will break while loop
else:
x += 1
continue
29
this is surprising for most people because the for-else statement is not well know but it pretty much means to only run the else block if the for block is not exited with a break.
With this in mind, YES, this code works but as a lot of other people said, this is NOT the best way to accomplish this task. Because #RahulVasta posted a good enough answer already, i wont. It is not to say that your logic does not work, but, since this is programming, there are infinite ways to approach a problem and some are better than others.

Related

Palindrome number in python (leetcode)

class Solution:
def isPalindrome(self, x: int) -> bool:
# If x is a negative number it is not a palindrome
# If x % 10 = 0, in order for it to be a palindrome the first digit should also be 0
if x < 0 and x%10 == 0):
return False
reversedNum = 0
while x > reversedNum:
reversedNum = reversedNum * 10 + x % 10
x = x // 10
# If x is equal to reversed number then it is a palindrome
# If x has odd number of digits, dicard the middle digit before comparing with x
# Example, if x = 23132, at the end of for loop x = 23 and reversedNum = 231
# So, reversedNum/10 = 23, which is equal to x
return True if (x == reversedNum or x == reversedNum // 10) else False
This is my code which is giving wrong output for 660,
Expected output : False
My output : True
Can someone tell me how to correct this.
reversedNum = 0
Num=x
while x > 0:
reversedNum = reversedNum * 10 + x % 10
x = x // 10
return True if (Num == reversedNum) else False
You don't really need an explicit check for a negative number because the while loop (in the following code) will not be entered and the return value will be an equality test between zero and some negative number - which is obviously False.
So:
def ispalindrome(x):
n = x
r = 0
while n > 0:
r *= 10
r += n % 10
n //= 10
return r == x
if you convert the number to a string is very simple. you only need to check that the string written backwards is the same
def ispalindrome(x):
return str(x) == str(x)[::-1]
ispalindrome(23132)
>>> True

Efficient way for checking number 3^x * 5^y

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

Project Euler #37 issue

I tried to solve Project Euler #37:
The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.
Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
I wrote my code in Python but I am facing weird issues.
Here's my code:
def isPrime(n):
if n == 2 or n == 3 or n == 5: return True
if n < 2 or n%2 == 0: return False
if n < 9: return True
if n%3 == 0: return False
if n%5 == 0: return False
r = int(n**0.5)
f = 5
while f <= r:
if n%f == 0: return False
if n%(f+2) == 0: return False
f +=6
return True
def gen(nb):
results = []
nb_str = str(nb)
for k in range(0, len(nb_str) - 1):
results.append(nb_str[k:])
results.append(nb_str[-k:])
return results
def check(nb):
for t in gen(nb):
if not isPrime(int(t)):
return False
return True
c = 0
s = 0
i = 2
while c != 11:
if check(i):
c += 1
s += i
i += 1
print(s)
Where does the error come from? (The expected result is 748317)
I suspect the errors coming from the results list
Yes, the gen() function is not working correctly as your slicing is off, also, you count 2, 3, 5 and 7 as truncatable primes which the question denies.
The second slice should be the other way around:
>>> s = 'abcd'
>>> for i in range(1,len(s)-1):
... print(s[i:])
... print(s[:-i])
...
bcd
abc
cd
ab
which we can see produces the right strings.
Altogether then, the function should be:
def gen(nb):
results = [nb]
nb_str = str(nb)
for k in range(1, len(nb_str)):
results.append(int(nb_str[k:]))
results.append(int(nb_str[:-k]))
return results
note I also added a string to int conversion - not sure how Python didn't make that obvious for you :/
And before get the full solution, Project Euler nearly always gives you an example which you can use to check your code:
>>> check(3797)
True
You must also add a condition in the check function to return False if the number is 2, 3, 5 or 7 as this is stated clearly in the question.
And the result is the expected: 748317.
Joe Iddon has explained the error in your code, but you can speed it up a little by turning gen into an actual generator. That way, you can stop checking the results for a given nb as soon as you detect a composite number (and gen will stop generating them). I've also made a few minor tweaks to your primality tester. Remember, the or operator short-circuits, so if a is True-ish in a or b then it doesn't bother evaluating b.
def isPrime(n):
if n in {2, 3, 5, 7}:
return True
if n < 2 or n%2 == 0:
return False
if n%3 == 0 or n%5 == 0:
return False
r = int(n**0.5)
f = 5
while f <= r:
if n%f == 0 or n%(f+2) == 0:
return False
f += 6
return True
def gen(nb):
yield nb
nb_str = str(nb)
for k in range(1, len(nb_str)):
yield int(nb_str[k:])
yield int(nb_str[:-k])
def check(nb):
for t in gen(nb):
if not isPrime(t):
return False
return True
c = s = 0
# Don't check single digit primes
i = 11
while c < 11:
if check(i):
c += 1
s += i
print(i)
i += 2
print('sum', s)
output
23
37
53
73
313
317
373
797
3137
3797
739397
sum 748317
In fact, you can get rid of the check function, and replace it with all, which also short-circuits, like or does. So you can replace the
if check(i):
with
if all(map(isPrime, gen(i))):

Python Fizzbuzz problems with loop

I've searched for the answer for about an hour, and it seems most people have coded fizzbuzz a different way than myself.
However, having tried everything to figure out why this simple code will not work I'm getting extremely frustrated.
Can anyone point out the simple problem I'm sure I'm having? The code runs but it just returns the value 1.
def fizzbuzz(intList):
for n in intList:
if n % 3 == 0 and n % 5 == 0:
return n.replace(str(n),"Fizzbuzz")
elif n % 3 == 0:
return n.replace(str(n),"Fizz")
elif n % 5 == 0:
return n.replace(str(n),"Buzz")
else:
return n
The first value it looks at is 1. Since 1%x is only 0 for an x of 1, it goes to the else and returns 1. And then it's done, because that's what return does.
That leads to the bigger problem, which is that you are starting a loop and then guaranteeing that you will leave that loop after only one iteration, because there's a return in every branch. You'll need to replace those return statements with either append()s to a list (don't forget to return the resulting list) or print() calls.
Also, if you started with something like 3, your code would try to use replace on an integer, which is not something you can do with integers. You would get a traceback.
The code is returning 1 because consider this list [1,2,3,4,5,6,7,8,9,10]. All three conditions will get false and the last else will return 1. If you want the answer, append them into list.
Something like this:
def fizzbuzz(intList):
temp = []
for n in intList:
if n % 3 == 0 and n % 5 == 0:
temp.append("Fizzbuzz")
elif n % 3 == 0:
temp.append("Fizz")
elif n % 5 == 0:
temp.append("Buzz")
else:
temp.append(n)
return temp
print fizzbuzz(range(1,20))
Perhaps if you take a look at this code you will
better understand yours. Although this is a completely
different implementation of fizzbuzz in Python3
#!/usr/bin/python3
for i in range(1,100):
msg = "Fizz" * bool(i%3==0)
msg += "Buzz" * bool(i%5==0)
if not msg:
msg = i
print(msg)
My skills in python are fairly average but i love using dicitonaries. Here is the Fizz Buzz program using dictionaries.Without an if.
for data in range(1, 101):
msg = [str((data % 3 == 0)), str((data % 5 == 0))]
// msg returns a list with ['True' ,'False'] depending on the condition
conveter = {"True False": "Fizz",
"False True": "Buzz",
"True True": "Fizz Buzz",
"False False": data
}
val = conveter[" ".join(msg)]
print(val)
I just implemented FizzBuzz as
for n in range(1, 100):
if n%15==0: print "FizzBuzz"
elif n%5==0: print "Buzz"
elif n%3==0: print "Fizz"
else: print n
The best thing with it that
It works
It fits into a tweet, with a margin
Years later, based on this...
FizzBuzz: For integers up to and including 100, prints FizzBuzz if the integer is divisible by 3 and 5 (15); Fizz if it's divisible by 3 (and not 5); Buzz if it's divisible by 5 (and not 3); and the integer otherwise.
def FizzBuzz():
for i in range(1,101):
print {
3 : "Fizz",
5 : "Buzz",
15 : "FizzBuzz"}.get(15*(not i%15) or
5*(not i%5 ) or
3*(not i%3 ), '{}'.format(i))
The .get() method works wonders here.
Operates as follows
For all integers from 1 to 100 (101 is NOT included),
print the value of the dictionary key that we call via get according to these rules.
"Get the first non-False item in the get call, or return the integer as a string."
When checking for a True value, thus a value we can lookup, Python evaluates 0 to False. If i mod 15 = 0, that's False, we would go to the next one.
Therefore we NOT each of the 'mods' (aka remainder), so that if the mod == 0, which == False, we get a True statement. We multiply True by the dictionary key which returns the dictionary key (i.e. 3*True == 3)
When the integer it not divisible by 3, 5 or 15, then we fall to the default clause of printing the int '{}'.format(i) just inserts i into that string - as a string.
Some of the output
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
how a python function should look like if we want to see the next result in the interactive mode of the python interpreter:
>>> fizz(15)
[ 1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz' ]
n = int(input())
out = []
for i in range(1, n):
if i % 3 == 0 and i % 5 == 0:
out.append("fizzbuzz")
continue
elif i % 3 == 0:
out.append("fizz")
continue
elif i % 5 == 0:
out.append("buzz")
continue
out.append(i)
print(out)
Answer as [1,2,'fizz']
x = int(input('Enter the number: '))
if x % 3 ==0 and x % 5 ==0:
print('FizzBuzz')
elif x % 3 ==0:
print('Fizz')
elif x % 5 ==0:
print('Buzz')
else:
print(f'{x} ¯\_(ツ)_/¯')

Palindromic prime number in python

So I'm trying to figure out how to find all the palindrome prime numbers between 2 numbers.
So far my code can find the palindrome but when I check for a prime number, it prints out the non-primes as well. And there are numbers which are printed multiple times.
Could you please help.
Thanks.
a = 0
b = 500
a += 1
for i in range(a,b):
if(str(i) == str(i)[::-1]):
if(i>2):
for a in range(2,i):
y = True
if(i%a==0):
y = False
break
if y:
print(i)
Based on your most recent code, you simply need to make sure that you reset y, which serves as your positive indicator of primality, for each number you test. Otherwise, it will stay False when you get to the number 4, the first composite number.
>>> a = 0
>>> b = 500
>>> a += 1
>>> for i in range(a,b):
y = True
if(str(i) == str(i)[::-1]):
if(i>2):
for a in range(2,i):
if(i%a==0):
y = False
break
if y:
print(i)
3
5
7
11
101
131
151
181
191
313
353
373
383
As you can see, all of these are prime. You can check the list of primes wolframalpha provides to be sure that no palindromic primes have been omitted. If you want to include 2, add a special case for that.
Please see my comments below:
a = 0
b = 500
a += 1
y = True
for i in range(a,b):
if(str(i) == str(i)[::-1]):
print (i) # <--- You print every number that is a palindrome
if(i>2):
for a in range(2,i):
if(i%a==0):
y = False # <--- This never gets set back to True
break
if y:
print(i)
i+=i # <--- This is doing nothing useful, because it's a "for" loop
Look at my code below, we don't need to initialize Y as well. A For-Else block works well.
a = 0
b = 500
a += 1
for i in range(a,b):
if(str(i) == str(i)[::-1]):
if(i>1):
for a in range(2,i):
if(i%a==0):
y = False
break
else:
print(i)
To get 2 included in the answer, just be sure to check the if condition as (i>1) as mentioned by #elias
Here is the pretty fast implementation based on "Sieve of Atkin" algorithm. I calculate all primes numbers up to the end and then filter only palindromic ones where number is greater or equal to start.
import math
import sys
def pal_primes(start,end):
return list(filter(lambda x: str(x)==str(x)[::-1] and x>=start, sieveOfAtkin(end)))
def sieveOfAtkin(limit):
P = [1,2,3]
sql = int(math.sqrt(limit))
r = range(1,sql+1)
sieve=[False]*(limit+1)
for x in r:
for y in r:
xx=x*x
yy=y*y
xx3 = 3*xx
n = 4*xx + yy
if n<=limit and (n%12==1 or n%12==5) : sieve[n] = not sieve[n]
n = xx3 + yy
if n<=limit and n%12==7 : sieve[n] = not sieve[n]
n = xx3 - yy
if x>y and n<=limit and n%12==11 : sieve[n] = not sieve[n]
for x in range(5,sql):
if sieve[x]:
xx=x*x
for y in range(xx,limit+1,xx):
sieve[y] = False
for p in range(5,limit):
if sieve[p] : P.append(p)
return P
if __name__=="__main__":
print(pal_primes(int(sys.argv[1]),int(sys.argv[2])))
Based on this thread:
Sieve Of Atkin Implementation in Python

Categories