1
$\begingroup$

I've read the Mathematica documentation and am certain there's way to do this with functional programming, but can't quite conceive yet how. I've taken a simple example (stating the series for remaining balance on a fixed-interest loan - ignoring the hairsplitting about whether the interest is calculated before or after the first payment is made. I have randomly chosen interest to be applied before payment).

Pj = principal at period j
pmt = payment
i = interest per period

month 0: P1 = P0(1 + i) - pmt
month 1: p2 = (P0(1 + i) - pmt)(1 + i) - pmt
month 2: p3 = ((P0(1 + i) - pmt)(1 + i) - pmt )
month 3: p4 = (((P0 (1 + i) - pmt)(1 + i) - pmt))(1 + i) - pmt

What I want to do is build the state at month N. This is purely practice/learning for building nested functions using Mathematica code. I know the fixed-interest loan-repayment equation is easily derived and easily solved, but my goal here is to learn how to do repeated function application for real-world things -- Nest[f, x, 3] is reminiscent of what I want to do but can't see how to make it work.

Here is what I have tried: pure function:

f = #1 (1 + i) - #2 &

apply it:

f[principal, payment]

response:

(1 + i) P - payment

so, some progress.

I can manually repeatedly apply the pure function thus:

f[(1 + i) P - payment, payment]

to get

(1 + i) ((1 + i) P - payment) - payment

obviously correct, but I can't help thinking that I could get the correct formula by means other than manual application (or a do-while kind of loop).

EDIT: I should point out that as soon as I reduce the pure function to one parameter (P - the remaining principal, which is the only thing that changes), the `Next function works.

I am trying to find out how to Nest functions of more than one variable

$\endgroup$
  • 1
    $\begingroup$ Is month 1: similar to month 2? Does this work: f[n_] := Nest[# (i + 1) - payment &, P, n]; f[2] $\endgroup$ – Algohi Feb 1 '15 at 6:46
  • $\begingroup$ Welcome to Mathematica Stack Exchange! In addition to Nest see also NestList, and while you're at it Fold and FoldList as well. If these answer your question I think this can be closed either as a duplicate or easily found in the documentation. If not please indicate how your needs differ. $\endgroup$ – Mr.Wizard Feb 1 '15 at 7:20
  • $\begingroup$ I realize this is not the point of your question, but you might want to look at RSolve, which may be able to derive a closed form solution for you. $\endgroup$ – Sjoerd C. de Vries Feb 1 '15 at 10:00
  • $\begingroup$ thanks to all; until one knows the existence of something that does exactly what is needed (in this case Fold, FoldList) it's quite difficult to ask the question succinctly. In any case, I know an answer to this now, and this can be a springboard for the rest of my function-construction learning $\endgroup$ – Paul_A Feb 1 '15 at 22:35
1
$\begingroup$

As Algohi pointed out, if payment is the same every month, then you can get a list of payments at each month via (for example)

NestList[# (i + 1) - payment &, P, 2]

(*{P, (1 + i) P - payment, (1 + i) ((1 + i) P - payment) - payment}*)

Otherwise, if payment varies each month, then you can nest functions of two variables using FoldList:

payments = Array[p, 4];
FoldList[# (i + 1) - #2 &, P, payments]

(*{P, (1 + i) P - p[1], (1 + i) ((1 + i) P - p[1]) - 
  p[2], (1 + i) ((1 + i) ((1 + i) P - p[1]) - p[2]) - 
  p[3], (1 + i) ((1 + i) ((1 + i) ((1 + i) P - p[1]) - p[2]) - p[3]) -
   p[4]}*)
$\endgroup$
  • $\begingroup$ thanks - I can do this for my (simple learning case):FoldList[# 1 (i + 1) - #2 &, P, Table[p, {4}]] $\endgroup$ – Paul_A Feb 1 '15 at 22:32
  • $\begingroup$ @user192127: True, or alternately you could use NestList[# (i + 1) - p &, P, 4]. $\endgroup$ – DumpsterDoofus Feb 1 '15 at 22:35
2
$\begingroup$

Years of Lisp programming makes think the most natural approach to this problem is find a tail-recursive function as a helper function that carries the state of process and does the recursion. The main function will just call the recursive function with the needed initial values.

nxt[val_, pay_, i_, n_] := nxt[val (1 + i) - pay, pay, i, n - 1]
nxt[val_, _, _, 0] := val
r[prin_, i_, pay_, n_] := nxt[prin, pay, i, n]

Then

r[p0, i, pmt, 3]

gives

(1 + i) ((1 + i) ((1 + i) p0 - pmt) - pmt) - pmt

Such tail recursions can be simply transformed in iterations done by Nest.

next[{val_, pay_, i_}] := {val (1 + i) - pay, pay, i}
f[prin_, i_, pay_, n_] := First @ Nest[next, {prin, pay, i}, n]

With these definitions

f[p0, i, pmt, 3]

also gives

(1 + i) ((1 + i) ((1 + i) p0 - pmt) - pmt) - pmt

Note that since Nest expects to apply a function of one variable, the state of the process is packaged up into a list.

$\endgroup$
  • $\begingroup$ thanks - agreed there's a multi-line (and maybe this is best, all things considered) way to do it. Thanks, appreciated. I'd vote up if I had 15 reputation). FoldList seems another way to achieve this in one step $\endgroup$ – Paul_A Feb 1 '15 at 22:30

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.