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$

9 Answers 9

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$
1
  • $\begingroup$ I would consider it as "wierdo style" ;) but +1 $\endgroup$
    – Wjx
    May 28, 2017 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$
1
  • $\begingroup$ @MrWizard, same style solution: tmp = h; NestList[(tmp = tmp /. {f -> g, g -> h, h -> f})[#] &, x, 5] $\endgroup$
    – garej
    May 30, 2017 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$
2
  • $\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$
    – Ray Shadow
    May 28, 2017 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$
    – webcpu
    May 28, 2017 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$
3
  • $\begingroup$ @Shadowray Thank you for pointing out my mistake $\endgroup$
    – wul
    May 28, 2017 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$
    – Ray Shadow
    May 28, 2017 at 18:11
  • $\begingroup$ @Shadowray Thank you again. I have changed my answer. $\endgroup$
    – wul
    May 29, 2017 at 4:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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