The Python function
def isPrime(n):
return all(n % i for i in xrange(2, n))
checks if a number is a prime number by using all
.
How can I write a function similar to all
in Mathematica?
initial side note: As J.M. correctly points out this is not an efficient implementation and serves only to illustrate behavior similar to the Python function all
.
If you are looking for a similar definition to the Python code you give, then you could use this:
isPrime[n_] := And @@ Table[Mod[n, i] != 0, {i, Range[2, n - 1]}]
This creates a table of either True
or False
for each i
in the range, and the And@@
means it replaces the head of the list, turning {True,False,True,...}
(Which is equivalent to List[True,False,True,...]
) into And[True,False,True,...]
and thus evaluates to true only if they are all true.
You can then find primes under 20 using:
Select[Range@20, isPrime]
{1, 2, 3, 5, 7, 11, 13, 17, 19}
This however includes 1, which it should not. You could also just use the build in prime checker:
Select[Range@20, PrimeQ]
{2, 3, 5, 7, 11, 13, 17, 19}
Update
To elaborate, all
in python takes an iterable object and returns true if all iterations are true. For the Mathematica code, And@@
is used on a realised list of booleans and returns True
if they are all true. So they are not strictly the same, but typically in Mathematica you do not have language specified "iterables".
You could pass around unevaluated iteration specfications quite simply however, allowing you to iterate in any way you see fit in functions that take these specifications as input. For instance implementing an all
-like function that can short circuit on the very first False found:
SetAttributes[iterable, HoldAll]
myAll[iterable[exp_, {var_, lower_, upper_}]] :=
Module[{run = upper >= lower, i = lower},
While[run,
If[exp /. var -> i,
If[i == upper, Return[True], i++], Return[False]];
]; True
]
Allowing the prime function you gave to be defined as:
dprimeQ[n_] := myAll[iterable[Mod[n, i] != 0, {i, 2, n - 1}]]
Select[Range@20, dprimeQ]
{1,2,3, 5, 7, 11, 13, 17, 19}
Which still includes 1 however.
isPrime[]
is not very efficient compared to the built-in PrimeQ[]
, of course. Here's an alternative definition: isPrime[n_Integer?Positive] := And @@ Thread[Mod[n, Range[2, n - 1]] != 0]
$\endgroup$
Commented
Oct 24, 2012 at 11:28
isPrime[n_Integer?Positive] := Catch[Fold[If[! #2, Throw[#2], #1 && #2] &, True, Thread[Mod[n, Range[2, n - 1]] != 0]]]
$\endgroup$
Commented
Oct 24, 2012 at 11:48
Thread[Mod[n, Range[2, n - 1]] != 0]
) but then short circuiting the following traversal (which I suspect And already does internally). Consider a slower comparison, for instance (Pause[1];Mod[n,i]!=0)
and test with isPrime[8]. For your version it takes 6 seconds on my system, while the solution posted in my answer returns after just 1 second.
$\endgroup$
PrimeQ
. $\endgroup$