How to Table $ 2n-1 $ for $ n $ from $ 2 $ to $ 50 $, except when $ n=3m-1 $ for another integer $ m $?
- 9,783
- 3
- 20
- 41
- 41
- 2
4 Answers
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
- 394,356
- 18
- 477
- 896
-
Very clever! +1 – ciao Nov 22 '18 at 09:30
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).
- 68,936
- 4
- 101
- 191
-
1You could also return
Nothingin the else case to remove the unwanted elements directly – Lukas Lang Nov 22 '18 at 07:03
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
- 106,770
- 7
- 179
- 309
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
- 15,542
- 3
- 40
- 78