# Fold a list but alternate used functions

Is there a clean way to fold a list but alternate functions used?

Say we call such function FoldAlternating. Then for example,

The FoldAlternating[{Plus,Times}, {1, 5, 2, 3, 3, 2, 5}]] would produce 235,

Because it is equivalent to Times[Plus[Times[Plus[Times[Plus[1, 5], 2], 3], 3], 2], 5].

Edit: For $$2$$ functions f,g and starting value v_: 1, I can do it recursively:

fa[f_, g_, list_, v_: 1, i_: 1] :=
If[i + 1 == Length[list], f[g[v, list[[i]]], list[[i + 1]]],
If[i == Length[list], g[v, list[[i]]],
fa[f, g, list, f[g[v, list[[i]]], list[[i + 1]]], i + 2]]]


where fa[Times, Plus, {5, 2, 3, 3, 2, 5}] gives the expected example from above.

ClearAll[foldRotate]
foldRotate = Module[{fl = #}, Fold[Last[fl = RotateLeft[fl]]@## &, ##2]] &;


Examples:

foldRotate[{Plus, Times}, {1, 5, 2, 3, 3, 2, 5}]

 235

foldRotate[{Plus, Times}, 1, {5, 2, 3, 3, 2, 5}]

 235

foldRotate[{foo, bar, fum}, {a, b, c, d, e}]

foo[fum[bar[foo[a, b], c], d], e]

• Clever! Very nice indeed. May 4, 2020 at 3:34
• Thank you @MarcoB.
– kglr
May 4, 2020 at 3:47

Maybe something like this:

ClearAll[foldAlternating];
foldAlternating[{f1_, f2_}, lst_] := Fold[
{First@#1 + 1, Replace[First@#1, {_?OddQ :> f1, _ :> f2}]@@{Last@#1, #2}} &,
{1, First@lst}, Rest@lst
] // Last;

foldAlternating[{Plus, Times}, {1, 5, 2, 3, 3, 2, 5}]
(* 235 *)


It would be easy enough to generalise such a function.

# EDIT

In fact, here is a generalisation:

ClearAll[foldAlternating];
foldAlternating[fnsLst_, lst_] := Fold[
{Mod[First@#1 + 1, Length[fnsLst]], (fnsLst[[First@#1 + 1]])@@{Last@#1, #2}} &,
{0, First@lst}, Rest@lst
] // Last;

foldAlternating[{Plus, Times}, {1, 5, 2, 3, 3, 2, 5}]
(* 235 *)

foldAlternating[{Plus, Times, Mod}, {1, 5, 2, 4}]
(* 0 *)

foldAlternating[{Plus, Times, Mod}, {1, 5, 2, 3, 3, 2, 5, 7, 10, 9}]
(* 8 *)


How about a simple loop? (I know we are not supposed to use loops in Mathematica, but unless it is very inefficient, I do not see problem myself using loops)

foldAlternating[f_, g_, lst_] := Module[{z, n},
z = f[lst[], lst[]];
op = g;
Do[
z = op[z, lst[[n]]];
op = If[op === f, g, f]
, {n, 3, Length@lst}
];
z
];


To use it

lst = {1, 5, 2, 3, 3, 2, 5};
foldAlternating[Plus, Times, lst]
(*235*)


Note, this assumes lst is at least 3 elements long. Easy to add error checking if needed.

ps. do not name your own functions starting with UpperCaseLetter so not to confuse them with Mathematica's own functions, unless they are inside your own package.