4

How to Table $ 2n-1 $ for $ n $ from $ 2 $ to $ 50 $, except when $ n=3m-1 $ for another integer $ m $?

Amr
  • 41
  • 2

4 Answers4

7

Using Drop, Riffle and Complement:

Drop[Range[5, 2 50 - 1, 2], {3, -1, 3} ]

{5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97}

Riffle[#, # + 2] &[2 Range[3, 50, 3] - 1]

same result

2 Complement[#, #[[;; ;; 3]]] & @ Range[2, 50] - 1;

same result

All three are faster than Pick+ Unitize combination from Henrik's answer:

nmax = 1000000;

e0 = Drop[Range[5, 2 nmax - 1, 2], {3, -1, 3} ]; // AbsoluteTiming

0.0102131

e1 = Riffle[#, # + 2] &[2 Range[3, nmax, 3] - 1]; // AbsoluteTiming // First

0.0126898

e2 = 2 Complement[#, #[[;; ;; 3]]] & @ Range[2, nmax] - 1; //  AbsoluteTiming // First

0.0354908

versus Henrik's

d = Pick[2 # - 1, Unitize[Mod[#, 3] - 2], 1] &@Range[2, nmax]; // AbsoluteTiming // First

0.0526116

and chyanog's method:

(k = Floor[(2 nmax + 1)/3] - 1; 
 res = Range[4, 3 k + 1, 3] + BitAnd[Range[k], 1];) // AbsoluteTiming // First

0.0125891

e0 == e1 == e2 == d == res

True

kglr
  • 394,356
  • 18
  • 477
  • 896
5

The condition to avoid can be rewritten using Mod, hence:

Table[If[Mod[n, 3] != 2, 2 n - 1, Nothing], {n, 2, 50}]

Or you can use Map /@ instead of Table:

If[Mod[#, 3] != 2, 2 # - 1, Nothing] & /@ Range[2, 50]

(Thanks to Lukas Lang for the easier use of Nothing).

bill s
  • 68,936
  • 4
  • 101
  • 191
4

An idiomatic way with Sow and Reap:

Reap[
  Do[If[Mod[n, 3] != 2, Sow[2 n - 1]], {n, 2, 50}]
  ][[2, 1]]

{5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97}

A harder to read, vectorized way: First create the list and pick the valid elements with Pick.

Pick[2 # - 1, Unitize[Mod[#, 3] - 2], 1] &@Range[2, 50]

{5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97}

The vectorized version is about 40 times faster:

nmax = 1000000;
a = Reap[Do[If[Mod[n, 3] != 2, Sow[2 n - 1]], {n, 2, nmax}]][[2, 1]]; // AbsoluteTiming // First
b = Table[If[Mod[n, 3] != 2, 2 n - 1, Nothing], {n, 2, nmax}]; // AbsoluteTiming // First
c = If[Mod[#, 3] != 2, 2 # - 1, Nothing] & /@ Range[2, nmax]; // AbsoluteTiming // First
d = Pick[2 # - 1, Unitize[Mod[#, 3] - 2], 1] &@Range[2, nmax]; // AbsoluteTiming // First
a == b == c == d

0.943828

0.907419

1.34615

0.018833

True

Henrik Schumacher
  • 106,770
  • 7
  • 179
  • 309
2

More efficient way

Clear["f*"];
f1[m_] := Module[{r = Range[4, 2 m - Mod[m, 3], 3]}, r[[1 ;; ;; 2]] += 1; r];
f2[m_] := Drop[Range[5, 2 m - 1, 2], {3, -1, 3}];

r1 = f1[10^7]; // RepeatedTiming
r2 = f2[10^7]; // RepeatedTiming

r1 == r2

{0.11, Null}

{0.14, Null}

True

chyanog
  • 15,542
  • 3
  • 40
  • 78