Find prime numbers with list comprehension - python

I was trying to write a code to select the prime numbers in a list. The user gives a limit and the program displays all prime number from 2 to the limit. I was trying to reduce the maximum amount of lines I could and was surprised with some situations I can't understand. If you can help me, I'd be grateful.
I wrote this code:
# returns all integers from 2 to a limit given by the user.
def primes(limit):
# generates the numbers.
lista = range(2, limit + 1)
p = 2
while p < limit:
#filters the prime numbers and places in a list.
lista = [i for i in lista if i == p or i % p != 0]
p += 1
return lista
def main():
#asks the user for the limit number.
l = int(input("Enter the limit: "))
#call the function which selects the numbers and returns the result.
return print(primes(l))
#Ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
main()
It runs as I expected, but when I tried deleting the first list assignment line and include the range function directly into the comprehension, it doesn't work. Why?
# returns all integers from 2 to a limit given by the user.
def primes(limit):
p = 2
while p < limit:
#filters the prime numbers and places in a list.
lista = [i for i in range(2, limit + 1) if i == p or i % p != 0]
#or lista = [i for i in range(2, limit + 1) if i == p or i % p != 0]
#or lista = [i for i in [*range(2, limit + 1)] if i == p or i % p != 0]
p += 1
return lista
def main():
#asks the user for the limit number.
l = int(input("Enter the limit: "))
#call the function which selects the numbers and returns the result.
return print(primes(l))
#Ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
main()
Other problem. As the line with range is not a list I fixed it only to improve the code, but when I changed the name of the value from 'lista' to another name, I saw that it doesn't work too. Why?
# returns all integers from 2 to a limit given by the user.
def primes(limit):
# generates the numbers.
nums = range(2, limit + 1)
p = 2
while p < limit:
#filters the prime numbers and places in a list.
lista = [i for i in nums if i == p or i % p != 0]
p += 1
return lista
def main():
#asks the user for the limit number.
l = int(input("Enter the limit: "))
#call the function which selects the numbers and returns the result.
return print(primes(l))
#ensures that the main program only runs when the functions have not been imported into another file.
if __name__ == '__main__':
main()
Thanks for your attention.

This one-liner works perfectly :
def primes(val):
return [x for x in range(2, val) if all(x % y != 0 for y in range(2, x))]
print(primes(10))

Thank you for your attention.I liked the answer of our friend Yash Makan, but when I tried larger numbers, like 100000, it never led me to the result (or I was not so patient to wait). So I continued thinking about the problem and got the following that is the fastest way to compute this problem I could achieve with list comprehension. Note how fast you can compute millions of numbers.
# returns all integers from 2 to a limit given by the user.
def primes(limit):
l = [i for i in range(2, limit + 1) if all(i % j != 0 for j in [2, 3, 5])]
lista = []
return [2, 3, 5] + [lista.append(i) or i for i in l if all( i % j != 0 for j in lista[:int((len(lista) ** .5) + 1)])]
def main():
l = int(input("Enter the limit: "))
return print(primes(l))
if __name__ == '__main__':
main()

Related

How I add to a list same number multiple times by count?

I've got 2 problems here.
my first problem is that the code shows me only one time a factor even though it's multiple x times by the same factor. I don't know how to add it to the factor list.
Another problem is I'm not sure in print - how the sep works and how can I write "*" only between elements of factor list.
I can't use any import functions here (intertools, maths etc.)
Please help me.
def factorize(n):
prvocisla = []
faktor = []
#prime numbers
for num in range(1, 2000):
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
prvocisla.append(num)
count = 0
for i in prvocisla:
if n % i == 0:
count += 1
faktor.append(i)
print(n, " =", *faktor , sep=' *', end='\n')
factorize(360)
My result:
360 * = *2 *3 *5
The right result:
360 = 2 * 2 * 2 * 3 * 3 * 5
I try the count function with adding same factor to the list "count times" but it shows me an Error.
The problem is that in your second 'for' loop you evaluate if there is a prime number in your number, but not how many times it is present.
To do this you need to repeat the cycle every time you find a prime number and divide the initial number by the prime number. this way you will get to 1 and get all the factors in the array.
Here the right code:
def factorize(n):
prvocisla = []
faktor = []
#prime numbers
for num in range(1, 2000):
if num > 1:
for i in range(2, num):
if (num % i) == 0:
break
else:
prvocisla.append(num)
count = 0
t = n # <-- a temporary variable which get n value
while t>1:
for i in prvocisla:
if t % i == 0:
count += 1
faktor.append(i)
t = t/i <-- divide t every time you find a factor
break
print(f"{n!s} = {' * '.join(str(k) for k in faktor)}")
factorize(360)
For the print I use the #CreepyRaccoon suggestion.

ZeroDivisionError when listing factors of a number

The program I am writing is tasked with creating a list of all possible factors of a number, excluding the number itself. My code is as follows:
def list_all_factors(num):
result = []
for i in range(0, num):
if num % i == 0:
result.append(i)
return result
When I call this function I get the following error:
ZeroDivisionError: integer division or modulo by zero
What is causing this issue, and how can I resolve it?
The for loop:
for i in range(0, num)
should be
for i in range(1, num)
We change the lower bound to avoid attempting to divide by zero.
That's because you are trying to divide by zero as the error says in the for loop. You should start the range from 1 to avoid it.
def list_all_factors(num):
result = []
for i in range(1, num+1):
if num % i == 0:
result.append(i)
return result
or list comprehension
def list_all_factors(num):
result = [i for i in range(1,num+1) if num % i == 0]
return result

Get a list of prime numbers in python 3

Beginner. I'm trying to return a list that includes all the prime numbers from 0 to num. Could someone please help me find what's wrong with my code? I always get an empty list. Thanks a lot! (I'm using python 3.6)
def task(num):
num = int(num)
lst = []
if num < 3:
return lst
else:
for i in range(3,num):
if not i & 1:
lst = lst
else:
primetest = range(3, int(i ** 0.5) + 1, 2)
for n in primetest:
if i % n != 0:
lst.append(i)
return lst
task(5)
Updates:
Thank you guys for all your comments! Really helpful.
This is what my revised code looks like.
def task(num):
num = int(num)
lst = []
if num < 2:
return lst
if num >= 2:
lst.append(2)
for i in range(3, num + 1):
if i % 2 == 1:
switch = True
for n in range(3, int(i ** 0.5) + 1, 2):
if i % n == 0:
switch = False
break
if switch:
lst.append(i)
return lst
The main problem lies with your inner for loop :
With your code you will append the list with i each time you find a number in the primetestrange that is not a divisor of i.
You might want to use a boolean here to store the fact that you found a divisor of i, then only append it to the list if you didn't.
To answer your question, your list is empty because the primetestrange is always empty in your example :
int(3**0.5) + 1 = 3 and int(5**0.5) + 1 = 3
range(3,3,2) = []
The array is empty because the range function will not include the upper limit, and since the inner loop is not doing what it should be expected to do in your code, the result will be an empty list until the parameter of the task function is superior or equal to 9
Your code gets it wrong on several counts, tell me if you understand why the following works?
def task(num):
num = int(num)
lst = [2]
if num < 3:
return lst
for i in range(3, num + 1):
if i % 2 == 1:
for n in range(3, int(i ** 0.5) + 1, 2):
if i % n == 0:
break
else:
lst.append(i)
return lst
(note: the for else clause is quite natural here, for else clauses are used when you search for something in a loop, you break when you find that something, if not break is encountered and the regular stopIteration is used to exit the loop the else part is performed, I say it is natural here since in pseudo code you would say something like "if my number can be divided by another number less than its square it is not prime, otherwise add it to the list of primes" see http://book.pythontips.com/en/latest/for_-_else.html for more detauls)
Its by no means a fast way to do it but I tried to stay as close to the spirit of your attempt while improving the aesthetics of the code
you can find prime numbers and the most dividable one in a dateset.`
a=[ int(x) for x in input("Enter 10 values: ").split() ]
c=[]
prime=[]
b=max(a)
for num in range(1,b+1):
for i in range(2,num):
if (num%i)==0:
break
else:
prime.append(num)
for i in a:
for j in prime:
if i%j==0:
c.append(i)
from collections import Counter
e=Counter(c)
f=e.most_common(1)
f
def prim(z):
lst = []
for i in range(2, z+1):
for j in range(2,i):
if i % j == 0:
break
else:
lst = lst + [i]
return lst
print(prim(20))
result:
[2, 3, 5, 7, 11, 13, 17, 19]

Finding the largest palindrome of the product of two 3-digit numbers in Python

So the challenge I'm trying to solve is to find the largest palindrome made from the product of two 3-digit numbers. I'm new to Python and so my code is not elegant or refracted yet, but there is a logical error that I can't seem to find.
def ispalindrome(n):
rev_n = str(n)[::-1]
if n == rev_n:
return True
else:
return False
first_num = 100
second_num = 100
mylist=[]
while first_num < 1000:
while second_num < 1000:
item = first_num * second_num
mylist.append(item)
second_num += 1
second_num = 100
first_num +=1
# print (mylist)
num_as_string = []
for i in mylist:
i = str(i)
num_as_string.append(i)
print("Total products of two 3-digit numbers: {}").format(len(num_as_string))
print("-----------------------------------------------------")
def convert_to_num_list(string_list):
new_num_list = []
item = int(string_list)
new_num_list.append(item)
return new_num_list
palindrome_list = []
for j in num_as_string:
if ispalindrome(j) == True:
palindrome_list.append(j)
palindrome_list.sort()
# print(palindrome_list)
x = convert_to_num_list(j)
largest_palindrome = max(x)
print("Total palindroms of product of two 3-digit numers: {}").format(len(palindrome_list))
print("Largest palindrome = {}").format(largest_palindrome)
The problem is that I'm getting the largest palindrome as 580085, which is 995*583 but is NOT the largest palindrome. I believe the largest palindrome is 906609, which is 993*913, but my code is not finding this. Can anyone help me with the flaw in my logic?
Your code does a lot of unnecessary conversion between numbers and strings, which made the error hard to find. The only place in the code that needs a string representation is when determining if the number is a palindrome or not. So that should be the only place that the code does the conversion.
The logic error is in your function convert_to_num_list(). It takes a string representation of one number and returns a 1-list containing that number. So, "123321" gets returned as [123321]. You then take the max() of that 1-list, which is always the value that was passed to convert_to_num_list(). So the code never keeps the largest value because if a smaller value comes in later it will be overwritten. The code reports 995*583 as the largest because it comes in later than 993*913, which in turn is because 995 > 993.
You can fix that error with an if statement, but the program is overcomplicated and may well contain other bugs. I recommend reducing the code to the essential task of producing the largest palindrome, without printing out the intermediate results, because the simpler the code the easier it is to see a logic error.
def ispalindrome(n):
return str(n) == str(n)[::-1]
mylist=[]
for first_num in range(100,1000):
for second_num in range(100,1000):
item = first_num*second_num
if ispalindrome(item):
mylist.append(item)
print(max(mylist))
This gives your expected answer:
906609
Here is a function for finding the largest palindrome of the product of two 3-digit numbers that I found in stackoverflow.
Link to what i found- https://stackoverflow.com/a/7460573
def is_pal(c):
return int(str(c)[::-1]) == c
maxpal = 0
for a in range(999, 99, -1):
for b in range(a, 99, -1):
prod = a * b
if is_pal(prod) and prod > maxpal:
maxpal = prod
print maxpal
n1=999
n2=999
k=0
sl=[]
while n1>1:
count=n1
while count>=1:
result=n1*count
res=str(result)
res1=res[::-1]
if (res==res1):
sl.insert(k,result)
k+=1
count=count-1
n1=n1-1
print("largest pelindrom of 3 digit product is is %d" %(max(sl)))
palin=[]
for a in (range(1,1000)):
for b in (range(1,1000)):
d = a*b
d=str(d)
if len(d)>5:
if d[0]==d[5]:
if d[1]==d[4]:
if d[2]==d[3]:
palin.append(d)
palin.sort()
print(palin[len(palin)-1])
Using List comprehension can reduce the lines of code but i'll give an alternate option so that it's more readable.
List_of_palindromes = [i*j for i in range(100,1000) for j in range(i,1000) if str(i*j)==str(i*j)[::-1]]
print(max(List_of_palindromes))
More Readable form
List_of_palindromes = []
for i in range(100,1000):
for j in range(100,1000):
if str(i*j)==str(i*j)[::-1]:
List_of_palindromes.append(i*j)
print(max(List_of_palindromes))
Check this out..!
This can be shortened but its better understandable this way(for beginners).
l = list(range(100, 1000))
m = list(range(100, 1000))
prod_max = 0
def is_palindrome(num):
temp = num
rev=0
while num > 0:
div = num%10
rev = rev*10 + div
num = num //10
if rev == temp:
return True
else:
return False
for i in range(len(l)):
for j in range(len(m)):
prod = l[i]*m[j]
if is_palindrome(prod) == True:
if prod > prod_max:
prod_max = prod
num1 = l[i]
num2 = m[j]
print(f'{prod_max} the product of {num1} and {num2} is a palindrome')

How to write a recursive function for palindromic primes?

I have been trying to write a Python program which uses a recursive function to find the palindromic primes between two integers supplied as input. Example of palindromic prime: 313
I already know how to write a recursive function for palindromes, but I am struggling with this one a lot. I would appreciate any help. Thanks
recursive function for palindromes
Presumably to do the palindrome check recursively you check the outer characters:
def is_pali(s):
if len(s) <= 1:
return True
else:
return s[0] == s[-1] and is_pali(s[1:-1])
Now you can iterate over the numbers and see which are palindromes:
[i for i in range(n, m) if is_pali(str(i))]
Since 30000 is the limit, this works (101101 is the smallest number it gets wrong):
>>> [n for n in range(2, 500) if str(n) == str(n)[::-1] and (2**n-1)%n == 1]
[2, 3, 5, 7, 11, 101, 131, 151, 181, 191, 313, 353, 373, 383]
You can of course also use the (2**n-1)%n == 1 primality test in your own recursive palindrome function that you already have.
http://en.wikipedia.org/wiki/Fermat_primality_test
Probably you already went through this idea but here's what I would do...
If you have a palindrome function like this one:
def palindrome(word):
if len(word) == 1 or (len(word) == 2 and word[0] == word[1]):
return True
else:
if word[0] == word[len(word)-1]:
return palindrome(word[1] + word[len(word)-2])
else:
return False
And let's say you have a function to figure out if a number is prime (this I take from here):
def is_prime(number):
if number > 1:
if number == 2:
return True
if number % 2 == 0:
return False
for current in range(3, int(math.sqrt(number) + 1), 2):
if number % current == 0:
return False
return True
return False
You can just call the validation when you find out if your number is a palindrome (casting it to str first).
The missing part is generate the combination of the two integers you might get but well, that's a simple one.
Hope this helps.
-Edit:
Adding a recursive function for getting primes:
def prime(number,limit = 1):
if limit == number:
return True
else:
if number % limit == 0 and limit != 1:
return False
else:
return prime(number, limit + 1)
Instead of recursive solution, what about using more effective list slicing?
def isPalindrome(number):
nstr = str(number)
return nstr == nstr[::-1]
This works by converting the number to string and comparing it's reversed counterpart. There is also known algorithm for determining the palindrome,
using global variable:
sum = 0
def is_palindrome(number):
return palindrome_sum(number) == number
def palindrome_sum(number):
global sum
if number != 0:
remainder = number % 10
sum = sum * 10 + remainder
palindrome_sum(number / 10) * 10 + remainder
return sum
For mathematical recursive function without global variable, this algorithm can be used:
import math
def is_palindrome(number):
return palindrome_sum(number) == number
def palindrome_sum(number, sum=0):
iters = 0
if number != 0:
iters = int(math.log10(number))
remainder = number % 10
sum = palindrome_sum(number / 10) + remainder * 10 ** iters
return sum
It uses the length of number to find it's position in the resulting number. The length can be computed by int(math.log10(number)).
This solution uses the Sieve of Eratosthenes to find the prime numbers less than n. It then uses a basic palindrome check which of those prime numbers are palindromes. The check avoids converting the ints to strs, which is a time consuming operation.
#!/usr/bin/env python2.7
def primeslt(n):
"""Finds all primes less than n"""
if n < 3:
return []
A = [True] * n
A[0], A[1] = False, False
for i in range(2, int(n**0.5)+1):
if A[i]:
j = i**2
while j < n:
A[j] = False
j += i
return (num for num in xrange(n) if A[num])
def is_palindrome(n):
digits = []
while n > 0:
digits.append(n%10)
n /= 10
return digits == digits[::-1]
def main():
while True:
try:
i = int(raw_input("Palindromic primes less than... "))
break
except ValueError:
print "Input must be an integer."
print filter(is_palindrome, primeslt(i))
if __name__ == '__main__':
main()
If you have any questions about how this code works, feel free to ask me by commenting on my answer. Best of luck!

Categories