5

I have the following problem, and even though I've tried Fold & Inner, Sow & Reap, et al. I can't figure out the clean way to do this.

Here's the problem. I have a list that starts as {a,b}. I want to apply the functions f[u,v] and g[x,y,z] a fixed number of times to this list. The diagram below shows one iteration of what I want to do.

enter image description here

The next iteration would use this new list {A,B,b} as its input, as follows:

enter image description here

So after doing this a set number of times, I'd like the "result" to be the first two columns of these computations. That is, if I did it two times (as above), I would be left with {{a,A,A},{b,B,B}}.

I can do this with a for loop of course, but I really believe there is a more "functional programmy" approach. I know this isn't strictly about Mathematica, but it's the language I'm most comfortable with and it's related to a project I'm working on.

Guest
  • 53
  • 3

2 Answers2

5
f1[{a_, b_, ___}] := {a, f[a, b], b};
g1[{a_, B_, b_}] := {g[a, B, b], B, b};
NestList[g1[f1[#]] &, {a, b}, 2][[All, 1 ;; 2]] // TableForm

(*

a                                                b
g[a,f[a,b],b]                                    f[a,b]
g[g[a,f[a,b],b],f[g[a,f[a,b],b],f[a,b]],f[a,b]]  f[g[a,f[a,b],b],f[a,b]]
*)

To get your nomenclature you may use:

NestList[g1[f1[#]] &, {a, b}, 2][[All, 1 ;; 2]] //. 
         {f[a, b] :> B, g[a, B, b] :> A, f[A, B] :> BB, g[A, BB, B] :> AA} // Transpose

(*
 {{a, A, AA}, {b, B, BB}}
*)
Dr. belisarius
  • 115,881
  • 13
  • 203
  • 453
  • I have another question which is similar, but is more difficult because this time the number of iterations is variable, based on the first list. Should I just ask a new question? – Guest Oct 23 '14 at 22:15
  • @Guest You'll need to modify the Nestlist[] third parameter based on your arguments. Give it a try before asking – Dr. belisarius Oct 23 '14 at 22:17
  • Oh but the problem is a little more complicated. Basically I need to do the iterations until the TOTAL of the first column is above a certain number. So if a+A+A is 9, then do another iteration, but if a+A+A is 10, stop. Here 10 is some fixed number. – Guest Oct 23 '14 at 22:20
  • @Guest So you'll need NestWhileList[] instead, but the same global logic applies – Dr. belisarius Oct 23 '14 at 22:24
  • WOW! You must know every command! :) – Guest Oct 23 '14 at 22:30
1

This does what you want:

With[{count = 3, start = {a, b}},
     Most /@ NestList[Composition[Prepend[Rest@#, g@@#]&,
                                  {#[[1]], f[#[[1]], #[[2]]], #[[2]]}&],
                      Append[start, 0], count]]

Explanation:

  • ...& defines an anonymous function. # accesses its argument, which is the list. [[n]] just gives the nth element of the list.
  • Composition composes the two functions, that is, applies the right one first, and then the left one.
  • NestList does the recursion, retaining the intermediate results.
  • Most removes the last element.
  • /@ (Map) applies Most to each element of the list returned by NestList
  • Append[start, 0] just adds a dummy argument to the initial list, so that Most can remove it again.
celtschk
  • 19,133
  • 1
  • 51
  • 106