Suppose we have a number list a
:
n = 1000000;
a = RandomReal[{0, 1}, {n}];
We want to generate a list c
with the same dimension of a
and the relationship between the elements of a
and c
is:
$c[[i]] == 2 a[[i]] +3$
I think there will be no doubt that the best way to get this c
is:
c = 2 a + 3
However, what if c
is a "piecewise" list i.e. elements in different part of c
are generated by different formula? For example, n/2
of the elements right in the middle of c
are 0.
while others still follow the formula above.
The most direct way I can think out is:
c1 = Table[If[n/4 + 1 <= i <= 3 n/4, 0., 2 a[[i]] + 3 ], {i, n}]; // AbsoluteTiming
{7.7380000, Null}
It's simple, but too slow.
While two approaches are fast:
(c2 = 2 a + 3 ;
c2[[n/4 + 1 ;; 3 n/4]] = ConstantArray[0., {n/2}];) // AbsoluteTiming
(c3 = ConstantArray[0., {n}];
c3[[1 ;; n/4]] = 2 a[[1 ;; n/4]] + 3 ;
c3[[3 n/4 + 1 ;; -1]] = 2 a[[3 n/4 + 1 ;; -1]] + 3;) // AbsoluteTiming
{0.0760000, Null} {0.0580000, Null}
But they are so dirty… And things will be worse when the dimension of the list becomes higher:
n=100;
b = RandomReal[{0, 1}, {n, n, n}]
d1 = Table[
If[n/4 + 1 <= i <= 3 n/4 && n/4 + 1 <= j <= 3 n/4 &&
n/4 + 1 <= k <= 3 n/4, 0., 2 b[[i, j, k]] + 3 ], {i, n}, {j,
n}, {k, n}]; // AbsoluteTiming
(d3 = ConstantArray[0, {n, n, n}];
d3[[1 ;; n/4]] = 2 b[[1 ;; n/4]] + 3;
d3[[3 n/4 + 1 ;; -1]] = 2 b[[3 n/4 + 1 ;; -1]] + 3;
d3[[n/4 + 1 ;; 3 n/4, 1 ;; n/4]] =
2 b[[n/4 + 1 ;; 3 n/4, 1 ;; n/4]] + 3;
d3[[n/4 + 1 ;; 3 n/4, 3 n/4 + 1 ;; -1]] =
2 b[[n/4 + 1 ;; 3 n/4, 3 n/4 + 1 ;; -1]] + 3;
d3[[n/4 + 1 ;; 3 n/4, n/4 + 1 ;; 3 n/4, 1 ;; n/4]] =
2 b[[n/4 + 1 ;; 3 n/4, n/4 + 1 ;; 3 n/4, 1 ;; n/4]] + 3;
d3[[n/4 + 1 ;; 3 n/4, n/4 + 1 ;; 3 n/4, 3 n/4 + 1 ;; -1]] =
2 b[[n/4 + 1 ;; 3 n/4, n/4 + 1 ;; 3 n/4, 3 n/4 + 1 ;; -1]] + 3;); // AbsoluteTiming
{12.8440000, Null} {0.1990000, Null}
And a nightmare when the region are irregular:
f1 = Table[If[i^2 + j^2 + k^2 <= n^2, 0., 2 b[[i, j, k]] + 3 ],
{i, n}, {j, n}, {k, n}]; // AbsoluteTiming
{7.4530000, Null}
A fast f3
with the method shown in c3
and d3
is of course possible, but I'd like to skip it now.
So my question is, as the title said, is there an approach that's both elegant as c1
and fast as c3
? Or at least not that slow as c1
and not that dirty as c3
? Or, I can't have my cake and eat it too?
I add the tag "difference-equations" because this question is in fact generated when I explore finite difference method.