Reputation: 11443
I've following code that I need to convert to list-comprehension
(one liner). However, I am unable to do so.
The code calculates prime numbers up-to input range of A
.
def sieve(A):
l = []
f = lambda x : int(x**0.5)
for p in range(2,A+1):
for i in range(2, f(p) + 1):
if p % i == 0:
break
else:
l.append(p)
return l
So far I've following which does not work. Especially the break
within for-loop
is throwing me off.
list(set([val for sublist in [[p for i in range(2, f(p) + 1) if p %i != 0 ] for p in range(2,A) ] for val in sublist]))
EDIT
Adding constraints for the problem.
The code can only be one statement, without eval
or exec
. The code must be at most 160 character long.
Upvotes: 1
Views: 2076
Reputation: 2327
[p for p in range(2,A+1) if next((i for i in range(2, int(p**0.5) + 1) if (p % i) == 0),None)==None]
Code is 100 chars long.
We use next() to break out of the iteration.
Explanation
def sieve(A):
[p for p in range(2,A+1) if getFirstDiv(p)==None]
def getFirstDiv(p):
next(divIter(p),None)
def divIter(p):
return (i for i in range(2, int(p**0.5) + 1) if (p % i) == 0)
OUTPUT
15 --> [2, 3, 5, 7, 11, 13]
10 --> [2, 3, 5, 7]
Upvotes: 1
Reputation: 4872
This one liner will do it:
[r for r in [i*all([i if i%j!=0 else 0 for j in range(2,i)]) for i in range(2,x)] if r>0]
You just need to set x
(the maximum value).
Note: it is not particularly efficient, although I'm guessing efficiency isn't the aim of this question.
Explanation (expanded code):
filtered = []
primes = []
for i in range(2,x):
# Check that all numbers up to i do not divide i
# I realise we only need to check up to int(sqrt(i))
condition = all([i if i%j!=0 else 0 for j in range(2,i)])
# Exploit Python's treatment of bool: number*True = number and number*False=0
filtered.append( i*condition )
for r in filtered:
# Take out all the zeros
if r>0:
primes.append(r)
Upvotes: 1