Chapter 6 Shapes III Perimeters of Shapes The

  • Slides: 10
Download presentation
Chapter 6 Shapes III: Perimeters of Shapes

Chapter 6 Shapes III: Perimeters of Shapes

The Perimeter of a Shape s 1 s 2 w To compute the perimeter

The Perimeter of a Shape s 1 s 2 w To compute the perimeter we need a function with s 1 four equations (1 for each Shape constructor). w The first three are easy … perimeter : : Shape -> Float s 2 perimeter (Rectangle s 1 s 2) = 2*(s 1+s 2) perimeter (Rt. Triangle s 1 s 2) = s 1 + s 2 + sqrt (s 1^2+s 2^2) perimeter (Polygon pts) = foldl (+) 0 (sides pts) w This assumes that we can compute the lengths of the sides of a polygon. This shouldn’t be too difficult since we can compute the distance between two points with dist. Between.

Recursive Def’n of Sides sides : : [Vertex] -> [Side] sides [] = []

Recursive Def’n of Sides sides : : [Vertex] -> [Side] sides [] = [] sides (v: vs) = aux v vs where aux v 1 (v 2: vs’) = dist. Between v 1 v 2 : aux v 2 vs’ aux vn [] = dist. Between vn v : [] -- aux vn [] = [dist. Between vn v] w But can we do better? Can we remove the direct recursion, as a seasoned functional programmer might?

Visualize What’s Happening B A C E D w The list of vertices is:

Visualize What’s Happening B A C E D w The list of vertices is: vs = [A, B, C, D, E] w We need to compute the distances between the pairs of points (A, B), (B, C), (C, D), (D, E), and (E, A). w Can we compute these pairs as a list? [(A, B), (B, C), (C, D), (D, E), (E, A)] w Yes, by “zipping” the two lists: [A, B, C, D, E] and [B, C, D, E, A] as follows: zip vs (tail vs ++ [head vs])

New Version of sides This leads to: sides : : [Vertex] -> [Side] sides

New Version of sides This leads to: sides : : [Vertex] -> [Side] sides vs = zip. With dist. Between vs (tail vs ++ [head vs]) Where zip. With is a predefined function that is just like zip except that it applies its first argument (a function) to each pair of values. For example: zip. With (+) [1, 2, 3] [4, 5, 6] [5, 7, 9]

Perimeter of an Ellipse There is one remaining case: the ellipse. The perimeter of

Perimeter of an Ellipse There is one remaining case: the ellipse. The perimeter of an ellipse is given by the summation of an infinite series. For an ellipse with radii r 1 and r 2: p = 2 pr 1(1 - S si) where s 1 = 1/4 e 2 si = si-1 (2 i-1)(2 i-3) e 2 4 i 2 e = sqrt (r 12 – r 22) / r 1 for i >= 1 Given si, it is easy to compute si+1.

Computing the Series next. El: : Float -> Float next. El e s i

Computing the Series next. El: : Float -> Float next. El e s i = s*(2*i-1)*(2*i-3)*(e^2) / (4*i^2) Now we want to compute [s 1, s 2, s 3, …]. To fix e, let’s define: aux s i = next. El e s i si+1 = si (2 i-1)(2 i-3) e 2 4 i 2 Can we capture So, we would like to compute: [s 1, this pattern? s 2 = aux s 1 2, s 3 = aux s 2 3 = aux (aux s 1 2) 3, s 4 = aux s 3 4 = aux (aux s 1 2) 3) 4, . . . ]

Scanl (scan from the left) w Yes, using the predefined function scanl: scanl :

Scanl (scan from the left) w Yes, using the predefined function scanl: scanl : : (a -> b) -> b -> [a] -> [b] scanl f seed [] = seed : [] scanl f seed (x: xs) = seed : scanl f newseed xs where newseed = f x seed w For example: scanl (+) 0 [1, 2, 3] [ 0, 1 = (+) 0 1, 3 = (+) 1 2, 6 = (+) 3 3 ] [ 0, 1, 3, 6 ] w Using scanl, the result we want is: scanl aux s 1 [2. . ]

Sample Series Values [s 1 = s 2 = s 3 = s 4

Sample Series Values [s 1 = s 2 = s 3 = s 4 = s 5 =. . . ] 0. 122449, 0. 0112453, 0. 00229496, 0. 000614721, 0. 000189685, Note how quickly the values in the series get smaller. . . r 1 = 2. 1 r 2 = 1. 5

Putting it all Together perimeter (Ellipse r 1 r 2) | r 1 >

Putting it all Together perimeter (Ellipse r 1 r 2) | r 1 > r 2 = ellipse. Perim r 1 r 2 | otherwise = ellipse. Perim r 2 r 1 where ellipse. Perim r 1 r 2 = let e = sqrt (r 1^2 - r 2^2) / r 1 s = scanl aux (0. 25*e^2) (map int. To. Float [2. . ]) aux s i = next. El e s i test x = x > epsilon s. Sum = foldl (+) 0 (take. While test s) in 2*r 1*pi*(1 - s. Sum)