# How to make sure Table or Do only runs through specific values?

I often need to generate or run through very large numbers of integers (we're talking {i, 1, 10^9} and higher) and want to add certain integers to a list, say list1.

So far what I've been doing is use the following structure:

list1 = {};
Do[If[PrimeQ[i] && Sort[IntegerDigits[i]] == Range[9], AppendTo[list1, i]], {i, 10^9}];
list1


(This is an example of a function that adds to list1 only those values that are prime as well as pandigital from 1 to 9)

Now I realise that this is probably a horribly inefficient way to generate lists. How can I ensure that my Do only runs through those functions which fulfil my criteria, e.g. being prime, or being divisible by 14, and so forth, and skips those which it doesn't need to run through - especially when I am running through 1 billion values for i? Is this even possible? Won't my function by definition have to run through every value anyway?

• Unless there is a pattern in the search that tells you what numbers to skip, I'm afraid you're going to have to check each number. Obviously there are more efficient ways to do this in Mathematica. – RunnyKine Mar 13 '14 at 3:24
• There are about 9! == 362880 pandigital numbers in this range and PrimePi[10^9] == 50847534 primes. So I'd create a list of pandigital numbers, then Scan it with PrimeQ and Sow/Reap the results. Why do you even try for i<10^8? – Kuba Mar 13 '14 at 6:18
• @Kuba that's a very good point, and would indeed be very useful for this particular problem – Aron Mar 13 '14 at 13:57
• Reap@Do[If[Sort@IntegerDigits@Prime[i] == Range[9], Sow@Prime[i]], {i,PrimePi[10^8] + 1, PrimePi[10^9]}] – Szabolcs Mar 13 '14 at 16:30

I interpret your question as a question of how to generically, conditionally, accumulate results, using syntax similar to Do or Table, rather than how to solve your particular problem most efficiently using some of its specifics.

Here is a generic implementation of a Table - like function which accumulates results conditionally:

SetAttributes[ctab,HoldAll];
ctab[expr_,test_,iter:({_Symbol,__}..)]:=
Module[{indices,indexedRes,sowTag,depth=Length[Hold[iter]]-1},
Hold[iter]/. {sym_Symbol,__}:>sym/. Hold[syms__]:>(indices:={syms});
indexedRes=
(Replace[#1,{x_}:>x]&)[
Last[
Reap[
Do[If[test,Sow[{expr,indices},sowTag]],iter],sowTag
]
]
];
(SplitBy[indexedRes,Array[Function[x,#1[[2,x]]&],{depth}]][[##1,1]]&)@@
Table[All,{depth+1}]
];


It accepts most standard specs for Table iterators, including the multi-dimensional case, and is a version of my answer here.

Here is how it can be used:

ctab[i,PrimeQ[i],{i,100}]

(* {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97} *)

(pr = ctab[i,PrimeQ[i]&&Sort@IntegerDigits[i]==Range[7], {i,10^7}])//Short//AbsoluteTiming

(*
{11.355387,
{1234657,1245763,1246537,1246573,1247563,1254367,1254637,1256347,
<<518>>,7564231,7621543,7624531,7625143,7625341,7641253,7642513,7652413}
}
*)

• I am sad/glad my too narrow perspective on this question may have precipitated your wonderfully instructive answer...which I will have to contemplate...it has been a long week... – ubpdqn Mar 13 '14 at 12:00
• @ubpdqn Thanks. But I am not at all sure that my interpretation of the question is the right one. – Leonid Shifrin Mar 13 '14 at 14:51

Here Prime /@ Range@PrimePi[10^9] generates a list of prime numbers, and do is only looping those numbers.

list1 = {};
Do[Sort[IntegerList[i]] == Range[9], AppendTo[list1, i]], {i, Prime /@ Range@PrimePi[10^9]}];
list1


This seems faster than the Select way:

AbsoluteTiming[Prime /@ Range@PrimePi[10^6];]


{0.022192, Null}

AbsoluteTiming[Select[Range[10^6], PrimeQ];]


{0.260821, Null}

The IntegerList function is undefined here so I am not sure what the code is precisely doing. But in case you want to find prime numbers with each digit different (as @ubpdqn points out), you can do

Select[FromDigits/@Permutations@Range@9, PrimeQ]


{}

This runs in less than a second but unfortunately nothing found. Permutations@Range@9 can be replaced with another list for broader searches.