5
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ Thanks. How can I recover the first two columns of the data though? $\endgroup$
    – Guest
    Commented Oct 23, 2014 at 16:54
  • $\begingroup$ Welcome to Mathematica.SE! I suggest the following: 1) As you receive help, try to give it too, by answering questions in your area of expertise. 2) Read the faq! 3) When you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge. Also, please remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign! $\endgroup$ Commented Oct 23, 2014 at 17:09
  • $\begingroup$ Related: (21281) $\endgroup$
    – Mr.Wizard
    Commented Oct 23, 2014 at 20:07

2 Answers 2

5
$\begingroup$
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}}
*)
$\endgroup$
5
  • $\begingroup$ 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? $\endgroup$
    – Guest
    Commented Oct 23, 2014 at 22:15
  • $\begingroup$ @Guest You'll need to modify the Nestlist[] third parameter based on your arguments. Give it a try before asking $\endgroup$ Commented Oct 23, 2014 at 22:17
  • $\begingroup$ 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. $\endgroup$
    – Guest
    Commented Oct 23, 2014 at 22:20
  • $\begingroup$ @Guest So you'll need NestWhileList[] instead, but the same global logic applies $\endgroup$ Commented Oct 23, 2014 at 22:24
  • $\begingroup$ WOW! You must know every command! :) $\endgroup$
    – Guest
    Commented Oct 23, 2014 at 22:30
1
$\begingroup$

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.
$\endgroup$
3
  • $\begingroup$ The problem is I need more than just the "end" of the iterations: I need the first two columns. That is, I need Most from every time these two functions are applied. $\endgroup$
    – Guest
    Commented Oct 23, 2014 at 17:00
  • $\begingroup$ Ah, OK, I misunderstood that. I'll change the code accordingly. $\endgroup$
    – celtschk
    Commented Oct 23, 2014 at 17:02
  • $\begingroup$ @Guest: OK, I think now it does what you meant. $\endgroup$
    – celtschk
    Commented Oct 23, 2014 at 17:06

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.