2
$\begingroup$

Suppose that it is required to find the values of $n$ such that Abs[2^n - 51] is a prime number. It is easy to determine that the first few values are $\{2,3,5,6,...\}_{n\geq 0}$. How can Mathematica code be written to determine further values?

$\endgroup$
6
  • 2
    $\begingroup$ Select[Table[{n, Abs[2^n - 51]}, {n, 0, 100}], PrimeQ[#[[2]]] &][[All, 1]] gives such numbers up to $n=100$ $\endgroup$
    – BlacKow
    Apr 8 '16 at 19:12
  • $\begingroup$ I understand how this works up to a point. That point is: What does the PrimeQ[#[[2]]] &][[All, 1]] portion do? PrimeQ verifies the prime value, but the rest? $\endgroup$
    – Leucippus
    Apr 8 '16 at 19:16
  • 1
    $\begingroup$ First you make a Table that consists of pairs {n,Abs[2^n-51}, then you need to select pairs where second half is prime - PrimeQ[#[[2]]]. Now you still have a list of pairs - effectively a matrix, you need only first column, but all rows, this is what [[All,1]] does. You probably want to read about pure functions and slots. It will help if you run every command separately. $\endgroup$
    – BlacKow
    Apr 8 '16 at 19:27
  • 4
    $\begingroup$ Select[Range[100], PrimeQ[2^# - 51] &] $\endgroup$
    – Bob Hanlon
    Apr 8 '16 at 20:03
  • 2
    $\begingroup$ Pick[#, PrimeQ[2^# - 51]] &@Range[1000] $\endgroup$
    – user1066
    Apr 9 '16 at 9:55
1
$\begingroup$

The three solutions provided in comments are all perfectly viable, and their performance is comparable as well:

nmax = 3000;
Select[Table[{n, Abs[2^n - 51]}, {n, 0, 3000}], 
       PrimeQ[#[[2]]] &][[All, 1]]; // RepeatedTiming
Select[Range[3000], PrimeQ[2^# - 51] &]; // RepeatedTiming
Pick[#, PrimeQ[2^# - 51]] &@Range[3000]; // RepeatedTiming
Cases[Range[nmax], x_ /; PrimeQ[2^x - 51]]; // RepeatedTiming

(* Out:
 {1.66, Null}
 {1.64, Null}
 {1.65, Null}
 {1.70, Null}
*)

However, in my opinion Bob Hanlon's approach using Select or RunnyKine's approach using Cases are the cleanest and most readable, and they also have the advantage of being automatically parallelizable. Parallelize must recognize that the test specified can be run in parallel on the first argument. This is quite convenient:

Parallelize@
    Select[Table[{n, Abs[2^n - 51]}, {n, 0, nmax}], 
           PrimeQ[#[[2]]] &][[All, 1]]; // RepeatedTiming

Parallelize@ Select[Range[nmax], PrimeQ[2^# - 51] &]; // RepeatedTiming

Parallelize[Pick[#, PrimeQ[2^# - 51]] &@Range[nmax]]; // RepeatedTiming

Parallelize@Cases[Range[nmax], x_ /; PrimeQ[2^x - 51]]; // RepeatedTiming

(*Out:
 {1.722, Null}
 {1.1, Null}
 {1.676, Null}
 {1.1, Null}
*) 

For instance, the timing of the "parallel Select" is comparable to manual parallelization:

Extract[
 range = Range[nmax], 
 Position[ParallelMap[PrimeQ[2^# - 51] &, range], True]
]; // RepeatedTiming

(* Out: {1.1, Null} *)
$\endgroup$
3
  • $\begingroup$ On my computer this is actually the fastest: Cases[Range@3000, x_ /; PrimeQ[2^x - 51]], strangely enough. And can also be Parallelized. $\endgroup$
    – RunnyKine
    Apr 10 '16 at 7:24
  • $\begingroup$ @RunnyKine Good point about the Cases option being parallelizable. I added it to the answer, but I could not see a time advantage to it on my system (see timings, on Win7-64 using MMA 10.4). $\endgroup$
    – MarcoB
    Apr 10 '16 at 7:39
  • $\begingroup$ On my system (Win 10 MMA 10.4) it's just slightly faster that Select: 1.70 vs 1.73 seconds. Same for the Parallelized versions: 0.5 vs 0.53 seconds. $\endgroup$
    – RunnyKine
    Apr 10 '16 at 7:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.