16
$\begingroup$

Is it possible to use the NestList command with two functions, one at every even step and apply the other at every odd step. If this is possible could someone share an example ?

$\endgroup$
18
$\begingroup$

Update:

I think that the cleanest way is to use ComposeList (as suggested by kglr), but with PadRight to generate {f,g,f,g,f,...} sequence:

ComposeList[PadRight[{}, 5, {f, g}], x]

{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]}

It can be easily generalized to a larger number of functions:

ComposeList[PadRight[{}, 5, {f, g, h}], x]

{x, f[x], g[f[x]], h[g[f[x]]], f[h[g[f[x]]]], g[f[h[g[f[x]]]]]}

Original answer:

Here is one possibilty using FoldList:

FoldList[If[OddQ[#2], f[#], g[#]]&, x, Range[4]]

{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]]}

$\endgroup$
15
$\begingroup$

I would probably use NestList in the semi-imperative style shown in the answer of kglr... but here is a way in functional style:

NestList[Apply[{#2@#, #3, #2} &], {x, f, g}, 5][[All, 1]]

(* {x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]} *)
$\endgroup$
  • $\begingroup$ I would consider it as "wierdo style" ;) but +1 $\endgroup$ – Wjx May 28 '17 at 2:21
12
$\begingroup$

We can apply R.M's method from How to apply or map a list of functions to a list of data?

I'll show an example with three functions to demonstrate generality; two work just as well.

fns = {f, g, h};

NestList[Last[fns = RotateLeft[fns]][#] &, x, 5]
{x, f[x], g[f[x]], h[g[f[x]]], f[h[g[f[x]]]], g[f[h[g[f[x]]]]]}
$\endgroup$
  • $\begingroup$ @MrWizard, same style solution: tmp = h; NestList[(tmp = tmp /. {f -> g, g -> h, h -> f})[#] &, x, 5] $\endgroup$ – garej May 30 '17 at 14:44
12
$\begingroup$

Update: Another variation on ComposeList:

ComposeList[PadRight[##, "Periodic"], x] &[{f, g}, 5]

{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]}

ComposeList[PadRight[##, "Periodic"], x] &[{f, g, h}, 5]

{x, f[x], g[f[x]], h[g[f[x]]], f[h[g[f[x]]]], g[f[h[g[f[x]]]]]}

Similarly, on FoldList:

FoldList[#2@# &, x, PadRight[##, "Periodic"]] &[{f, g, h}, 5]

{x, f[x], g[f[x]], h[g[f[x]]], f[h[g[f[x]]]], g[f[h[g[f[x]]]]]}

And a variation on @WReach's approach:

foo = {{f, g }[[#2]]@#, 3 - #2} & @@ # &;
NestList[foo, {x, 1}, 5][[All, 1]]

{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]}

Original post:

Using NestList

i = 1; NestList[{f1, f2}[[Mod[i++, 2, 1]]][#] &, x, 5]

{x, f1[x], f2[f1[x]], f1[f2[f1[x]]], f2[f1[f2[f1[x]]]], f1[f2[f1[f2[f1[x]]]]]}

We get the same result using ComposeList:

ComposeList[{f1, f2}[[Mod[Range[5], 2, 1]]], x]

or FoldList in alternative ways:

FoldList[{f1, f2}[[Mod[#2, 2, 1]]][#] &, x, Range@5]
FoldList[#2@# &, x, {f1, f2}[[Mod[Range[5], 2, 1]]]]
$\endgroup$
4
$\begingroup$
FoldList[#2[#1] &, x, Riffle[Table[f, 3], g]]

(* {x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]} *)
$\endgroup$
3
$\begingroup$

Here's my take using a counter:

Block[{i = 1}, NestList[Unevaluated[{f, g}[[ Mod[i++, 2, 1] ]] ], x, 5]]
{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]}

A golfier variation of the same (but vulnerable to existing definitions of f[g]):

Block[{i = 0}, NestList[Unevaluated[f[g][[i++~Mod~2]]], x, 5]]
$\endgroup$
1
$\begingroup$

In:

nest[f_, g_, x_, n_] /; EvenQ[n] := Nest[g@*f, x, n/2]
nest[f_, g_, x_, n_] /; OddQ[n] := f@Nest[g@*f, x, (n - 1)/2]
nestlist[f_, g_, x_, n_] := Table[nest[f, g, x, i], {i, 0, n}]
nestlist[f, g, x, 5]

Out:

{x, f[x], g[f[x]], f[g[f[x]]], g[f[g[f[x]]]], f[g[f[g[f[x]]]]]}
$\endgroup$
  • $\begingroup$ This solution works but not exactly like NestList. Because NestList calculates f[x] only once, and then uses that value in the next iterations, while this solution will recalculate f[x] on each step. This can be important if f has side effects i.e. f[x_] := (Print["Calculating f[", x, "]"]; ff[x]). $\endgroup$ – Shadowray May 28 '17 at 9:42
  • $\begingroup$ @Shadowray Thanks! It's a surprise. I didn't know NestList calculate f[x] only once. And I assumed that f and g are purely functional functions. I made too many assumptions in this case. $\endgroup$ – UnchartedWorks May 28 '17 at 9:59
1
$\begingroup$

NetList is not really the right choice for this, but you can use Nest with Sow and Reap the intermediate results. E.g.,

ClearAll[f, g]
Last@Last@Reap@Nest[Sow@f[Sow@g[#]] &, x0, 3]
$\endgroup$
0
$\begingroup$
Nest[If[Head@# === g, f, g]@# &, x, 6]

This is a bad solution. Now I changed it.

f[g_, f_, n_] := 
    Module[{g1, f1}, 
    NestList[If[Head@# === g1, f1, g1]@# &, x, n] /. {g1 -> g, f1 -> f}]

To avoid recalculating f[x] at each step:

f[g_, f_, n_] := 
    NestList[If[Head@# === Hold[g], Hold[f], Hold[g]]@ReleaseHold@# &, x, n + 1][[2 ;;, 1]]
$\endgroup$
  • $\begingroup$ @Shadowray Thank you for pointing out my mistake $\endgroup$ – wul May 28 '17 at 17:55
  • $\begingroup$ No problem. Note that your new solution has the same specifics as the one by UnchartedWorks. I.e. it will recalculate f[x] at each step. $\endgroup$ – Shadowray May 28 '17 at 18:11
  • $\begingroup$ @Shadowray Thank you again. I have changed my answer. $\endgroup$ – wul May 29 '17 at 4:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.