A clean way to conceptually extract Parts from a circular list
Perhaps ArrayPad
:
ClearAll[f1]
f1 = ArrayPad[##, #] &;
Examples:
f1[{a, b, c, d}, {0, 1}]
{a, b, c, d, a}
f1[{a, b, c, d}, {1, 0}]
{d, a, b, c, d}
f1[{a, b, c, d}, {12, 0}]
{a, b, c, d, a, b, c, d, a, b, c, d, a, b, c, d}
Alternatively, you can use "Periodic"
as the third argument in ArrayPad
:
ClearAll[f2]
f2 = ArrayPad[##, "Periodic"] &
Update: We can combine ArrayPad
and Part
:
ClearAll[f0]
f0[a_, b_, c_: All] := ArrayPad[a, b, a][[c]]
Examples:
f0[{a, b, c, d}, {0, 1}](* append first *)
{a, b, c, d, a}
f0[{a, b, c, d}, {1, 0}] (* prepend last *)
{d, a, b, c, d}
f0[{a, b, c, d}, {1, 1}](*append first and prepend last*)
{d, a, b, c, d, a}
f0[{a, b, c, d}, {1, -1}](* rotate right *)
{d, a, b, c}
f0[{a, b, c, d}, {-1, 1}] (* rotate left *)
{b, c, d, a}
f0[{a, b, c, d}, {0, 8}] (* repeat *)
{a, b, c, d, a, b, c, d, a, b, c, d}
f0[{a, b, c, d}, {9, -1}] (* rotate right and repeat *)
{d, a, b, c, d, a, b, c, d, a, b, c}
f0[{a, b, c, d}, {-1, 9}] (* rotate left and repeat *)
{b, c, d, a, b, c, d, a, b, c, d, a}
f0[{a, b, c, d}, {0, 0}, -1 ;; 1 ;; -1] (* reverse *)
{d, c, b, a}
f0[{a, b, c, d}, {0, 8}, ;; ;; 2] (*repeat and take odd parts*)
{a, c, a, c, a, c}
f0[{a, b, c, d}, {0, 8}, {1, 3, 4, 7, 9}] (*repeat and take parts 1,3,4,7 and 9*)
{a, c, d, c, a}
It turns out we can do all the required transformations using only Partition
using the (undocumented) sixth argument to do arbitrary-post-processing:
ClearAll[☺]
☺[a_, b_, c_, d_: ;;] := Partition[a, b, b, c, a, ## & @@ {##}[[d]] &];
Examples:
☺[{a, b, c, d}, 5, 1] (* append first*)
{a, b, c, d, a}
☺[{a, b, c, d}, 5, 2] (* prepend last*)
{d, a, b, c, d}
☺[{a, b, c, d}, 4, 2] (*rotate right *)
{d, a, b, c}
☺[{a, b, c, d}, 4, -1] (*rotate left *)
{b, c, d, a}
☺[{a, b, c, d}, 4, 1, -1 ;; 1 ;; -1] (* reverse *)
{d, c, b, a}
☺[{a, b, c, d}, 12, 1] (* repeat *)
{a, b, c, d, a, b, c, d, a, b, c, d}
☺[{a, b, c, d}, 12, 1, ;; ;; 2] (* repeat and take odd parts *)
{a, c, a, c, a, c}
☺[{a, b, c, d}, 12, 1, {1, 3, 4, 7, 9}] (* repeat and take parts 1,3,4,7 and 9*)
{a, c, d, c, a}
NOTE: Unfortunately, ☺
works only in versions prior to 12.0.0; it doesn't work in version 12.0.0 (thanks: Christopher Lamb).
Update: The same idea used with Part
as in MannyC's answer:
ClearAll[☺☺]
☺☺[a_, b_, c_, d_: All] := a[[Mod[c - 1 + Range[b], Length@a, 1][[d]]]];
Examples:
☺☺[{a, b, c, d}, 5, 1] (* append first *)
{a, b, c, d, a}
☺☺[{a, b, c, d}, 5, 4] (* prepend last *)
{d, a, b, c, d}
☺☺[{a, b, c, d}, 4, 4](* rotate right *)
{d, a, b, c}
☺☺[{a, b, c, d}, 4, 2](* rotate left *)
{b, c, d, a}
☺☺[{a, b, c, d}, 4, 1, -1 ;; 1 ;; -1] (* reverse*)
{d, c, b, a}
☺☺[{a, b, c, d}, 12, 1] (* repeat *)
{a, b, c, d, a, b, c, d, a, b, c, d}
☺☺[{a, b, c, d}, 12, 1, ;; ;; 2] (*repeat and take odd parts*)
{a, c, a, c, a, c}
☺☺[{a, b, c, d}, 12, 1, {1, 3, 4, 7, 9}] (*repeat and take parts 1,3,4,7 and 9*)
{a, c, d, c, a}
This requires a bit of redundant memory but it also opens the door to vectorization:
this = {a, b, c};
next = RotateLeft[this];
prev = RotateRight[this];
Now you can do cute things like this:
(next - 2 this + prev)/h^2