Functional Programming II (Lec06)

yukita@k.hosei.ac.jp

•Fold

Fold[f, x, {a, b, c}]

f[f[f[x, a], b], c]

myFact[n_] := Fold[Times, 1, Range[n]]

myFact[3]

6

myFact[5]

120

Horner's method is given by

Fold[#1 x + #2 &, 0, {a, b, c, d, e}]

e + x (d + x (c + x (b + a x)))

% // Expand

e + d x + c x^2 + b x^3 + a x^4

Alternating sum is given by

myAlternatingSum[x_List] := Fold[(#2 - #1) &, 0, Reverse[x]]

myAlternatingSum[Array[f, 10]]

f[1] - f[2] + f[3] - f[4] + f[5] - f[6] + f[7] - f[8] + f[9] - f[10]

The myUnion function acts the same as builtin function Union except that it does no sorting prior to output.

myUnion[x_List] := Fold[If[MemberQ[#1, #2], #1, Append[#1, #2]] &, {First[x]}, Rest[x]]

myUnion[{a, b, c, c, b, a, z, y, x, 3, 1, 2, x, y, z}]

{a, b, c, z, y, x, 3, 1, 2}

•Thread

Thread[f[{a, b, c}, d, {x, y, z}]]

{f[a, d, x], f[b, d, y], f[c, d, z]}

data = {{"Taro", 100, 90, 70},          &nbs ... ;           {"Kimimaro", 60, 50, 100}}

{{Taro, 100, 90, 70}, {Hanako, 90, 70, 80}, {Jiro, 70, 65, 55}, {Hideki, 100, 50, 70}, {Kimimaro, 60, 50, 100}}

We are going to calculate the average scores of Database, Operating System, and Computer Architecture. To do this we extract the numerical data part from data.

data0 = Map[Rest, data]

{{100, 90, 70}, {90, 70, 80}, {70, 65, 55}, {100, 50, 70}, {60, 50, 100}}

Compare the following. The first and second usage returns the same result, which is not what we expected. The third and fourth ones come up with what we need.

Thread[f[data0]]

{f[{100, 90, 70}], f[{90, 70, 80}], f[{70, 65, 55}], f[{100, 50, 70}], f[{60, 50, 100}]}

Thread[f @ data0]

{f[{100, 90, 70}], f[{90, 70, 80}], f[{70, 65, 55}], f[{100, 50, 70}], f[{60, 50, 100}]}

Thread[f @@ data0]

{f[100, 90, 70, 100, 60], f[90, 70, 65, 50, 50], f[70, 80, 55, 70, 100]}

Thread[Apply[f, data0]]

{f[100, 90, 70, 100, 60], f[90, 70, 65, 50, 50], f[70, 80, 55, 70, 100]}

Let us try the third way with f replaced by Plus, which produces the list of the average scores of the three subjects.

sums = Thread[Plus @@ data0]

{420, 325, 375}

sums/Length[data]

{84, 65, 75}

Let us do it all in one-liner.

Thread[Plus @@ Map[Rest, data]]/Length[data]

{84, 65, 75}

Thread[Apply[Plus, Map[Rest, data]]]/Length[data]

{84, 65, 75}

We will see, in the next section, much elegant solution to the averaging.

•MapThread

data0

{{100, 90, 70}, {90, 70, 80}, {70, 65, 55}, {100, 50, 70}, {60, 50, 100}}

MapThread[f, data0]

{f[100, 90, 70, 100, 60], f[90, 70, 65, 50, 50], f[70, 80, 55, 70, 100]}

MapThread[Plus, Map[Rest, data]]

{420, 325, 375}

The average scores are obtained as follows.

MapThread[Plus, Map[Rest, data]]/Length[data]

{84, 65, 75}

•Map(revisited)

We would like to append a new field to each record. The new field contains the average score of the three subjects of each person.

Map[Append[#, Plus @@ Rest[#]/3.0] &, data] // MatrixForm

( Taro                 100                  90                   70                   86.66666 ... 33333`    Kimimaro             60                   50                   100                  70.`

Map[Append[#, Plus @@ Rest[#]/3.0] &, data] // MatrixForm

•Exercises

•Problem 1 (Mandatory)

Using  Fold,  define the sumTo function that returns

1 + 2 + ··· + n

when called as sumTo[n].

•Solution

•Problem 2 (Optional)

Write a one-liner program that outputs the list of the variances of three subjects on input of data given in the Section of "Thread." Use MapThread for readability.

•Solution

Converted by Mathematica  (May 20, 2003)