Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:2023:haskell:l08_2 [2023/04/27 13:26]
george.vanuta
pp:2023:haskell:l08_2 [2023/04/27 14:16] (current)
george.vanuta
Line 68: Line 68:
 ===== 8.3. Infinite Binary Trees ===== ===== 8.3. Infinite Binary Trees =====
  
-Defining a simple binary tree structure in //Haskell// is easy.\\+Defining a simple ​**binary tree** structure in //Haskell// is easy.\\
 Take this for example: Take this for example:
  
Line 91: Line 91:
 </​code>​ </​code>​
  
-But what if we want to enforce an infinite binary tree?\\+But what if we want to enforce an **infinite binary tree**?\\
 The solution is eliminating the need for the empty node ''​Nil'':​ The solution is eliminating the need for the empty node ''​Nil'':​
  
Line 101: Line 101:
 </​code>​ </​code>​
  
-**8.3.1.** Define the ''​repeatTree''​ function which takes an **Int** '​k'​ and generates an infinite tree, where each node has the value ''​k''​.+**8.3.1.** Define the ''​repeatTree''​ function which takes an **Int** ​''k'' and generates an **infinite tree**, where each node has the value ''​k''​.
  
 <code haskell> <code haskell>
- 
- 
  
 {- {-
Line 126: Line 124:
 </​code>​ </​code>​
  
-===== 8.3. Numerical Approximations =====+**8.3.2.** In order to view an **infinite tree**, we need to convert it to a finite **binary tree**. Define the function ''​sliceTree'',​ which takes a level ''​k'',​ an **infinite tree** and returns the first ''​k''​ levels of our tree, in the form of a finite one.
  
-**8.3.1.** Define the ''​build''​ function which takes a generator ''​g''​ and an initial value ''​a0''​ and generates the **stream**: ''​[a0,​ g a0, g (g a0), g (g (g a0)), .%%.%%. ]''​.+<code haskell>​ 
 + 
 +{- 
 +> sliceTree 2 (repeatTree 3) 
 + 
 +       3 
 +       | 
 +   ​---------- 
 +   ​| ​       | 
 +   ​3 ​       3 
 +------ ​   ------  
 +|    |    |    | 
 +Nil  Nil  Nil  Nil 
 +-} 
 + 
 +sliceTree :: Int -> StreamBTree -> BTree 
 + 
 +</​code>​ 
 + 
 +**8.3.3.** Define the ''​generateTree''​ function, which takes a **root** ''​k'',​ a **left generator** function ''​leftF''​ and a **right generator** function ''​rightF''​.\\ 
 +For example, let's say we have ''​k=2'',​ ''​leftF=(+1)'',​ ''​rightF=(*2)''​. This should generate a tree where the //root// is $math[2], the //left child// is $math[parent + 1]\\ 
 +and the //right child// is $math[parent * 2]. 
 + 
 +<code haskell>​ 
 + 
 +{- 
 +> generateTree 2 (+1) (*2) 
 +                                    2 
 +                                    | 
 +               ​------------------------------------------- 
 +               ​| ​                                        ​| ​            
 +               ​3 ​                                        4 
 +        ----------------- ​                        ​----------------- ​   
 +        |               ​| ​                        ​| ​              | 
 +        4               ​6 ​                        ​5 ​              8 
 +    --------- ​      ​--------- ​                ​--------- ​      ​--------- 
 +    |       ​| ​      ​| ​      ​| ​                ​| ​      ​| ​      ​| ​      | 
 +    5       ​8 ​      ​7 ​      ​12 ​               6       ​10 ​     9       16 
 +  -----   ​----- ​   -----   ​----- ​           -----   ​----- ​   -----   -----  
 +  |   ​| ​  ​| ​  ​| ​   |   ​| ​  ​| ​  ​| ​           |   ​| ​  ​| ​  ​| ​   |   ​| ​  ​| ​  | 
 +  6   ​10 ​ 9   ​16 ​  ​8 ​  ​14 ​ 13  24           ​7 ​  ​12 ​ 11  20   ​10 ​ 18  17  32 
 +  .   ​. ​  ​. ​  ​. ​   .   ​. ​  ​. ​  ​. ​           .   ​. ​  ​. ​  ​. ​   .   ​. ​  ​. ​  . 
 +  .   ​. ​  ​. ​  ​. ​   .   ​. ​  ​. ​  ​. ​           .   ​. ​  ​. ​  ​. ​   .   ​. ​  ​. ​  . 
 +-} 
 + 
 +generateTree :: Int -> (Int -> Int) -> (Int -> Int) -> StreamBTree 
 + 
 +</​code>​ 
 + 
 +===== 8.4. Numerical Approximations ===== 
 + 
 +**8.4.1.** Define the ''​build''​ function which takes a generator ''​g''​ and an initial value ''​a0''​ and generates the **stream**: ''​[a0,​ g a0, g (g a0), g (g (g a0)), .%%.%%. ]''​.
  
 <code haskell> <code haskell>
Line 142: Line 191:
 </​code>​ </​code>​
  
-**8.3.2.** Using the ''​build''​ function, define the following **streams**:​+**8.4.2.** Using the ''​build''​ function, define the following **streams**:​
  
 <code haskell> <code haskell>
Line 157: Line 206:
 </​code>​ </​code>​
  
-**8.3.3.** Define the ''​select''​ function which takes a **tolerance** ''​e''​ and a **stream** ''​s''​ and returns the ''​nth''​ element of the **stream** which satisfies the following condition: ​ $math[\lvert s_n - s_{n+1} \rvert < e].+**8.4.3.** Define the ''​select''​ function which takes a **tolerance** ''​e''​ and a **stream** ''​s''​ and returns the ''​nth''​ element of the **stream** which satisfies the following condition: ​ $math[\lvert s_n - s_{n+1} \rvert < e].
  
 <code haskell> <code haskell>
Line 167: Line 216:
 ==== Mathematical Constants ==== ==== Mathematical Constants ====
  
-**8.3.4.** +**8.4.4.** 
  
 Knowing that $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi], where $math[F_n] is the nth element of the **Fibonacci** sequence, write an\\ Knowing that $math[\displaystyle \lim_{n \rightarrow \infty} \frac{F_{n+1}}{F_n} = \varphi], where $math[F_n] is the nth element of the **Fibonacci** sequence, write an\\
Line 178: Line 227:
 </​code>​ </​code>​
  
-**8.3.5.** +**8.4.5.** 
  
 Consider the //​sequence//:​ Consider the //​sequence//:​
Line 194: Line 243:
 ==== Square Root ==== ==== Square Root ====
  
-**8.3.6.** +**8.4.6.** 
  
 Given a number ''​k'',​ we want to create a function which calculates the\\ Given a number ''​k'',​ we want to create a function which calculates the\\
Line 213: Line 262:
 ==== Derivatives ==== ==== Derivatives ====
  
-**8.3.7.** +**8.4.7.** 
  
 We can approximate the derivative of a function in a certain point using the definition of the derivative: We can approximate the derivative of a function in a certain point using the definition of the derivative:
Line 228: Line 277:
  
 derivativeApprox :: (Double -> Double) -> Double -> Double derivativeApprox :: (Double -> Double) -> Double -> Double
- 
-</​code>​ 
- 
-==== The Newton-Raphson Method ==== 
- 
-**8.3.8.** ​ 
- 
-The method used for approximating the square root is derived from a more general one, named **The Newton-Raphson Method**. 
- 
-This is a generic method used for finding the **roots** of a function ($math[x] | $math[f(x) = 0]). 
- 
-Considering the following //​sequence//:​ 
- 
-$math[x_{n+1} = x_n - \frac{f(x_n)}{f'​(x_n)}] 
- 
-and the //limit//: 
- 
-$math[\displaystyle \lim_{n \rightarrow \infty} x_n = r\ \Rightarrow \ f(r) = 0] 
- 
-write a function which takes another ''​function''​ and it approximates a root with **tolerance** ''​e=0.00001''​. Make use of ''​build'',​ ''​select''​ and ''​derivativeApprox''​. 
- 
-<code haskell> 
- 
-rootApprox :: (Double -> Double) -> Double 
- 
-</​code>​ 
- 
-==== Integrals (:< ==== 
- 
-**8.3.9.** ​ 
- 
-Given a function $math[f], we can approximate the definite integral on $ [a, b]$, using the area of the trapezoid defined by $math[a, b, f(a), f(b)]: 
- 
-$math[\displaystyle \int_{a}^{b} f(x) dx \approx (b - a)\frac{f(a)+f(b)}{2}] 
- 
-We can obtain a better approximation by dividing the interval in two and adding the area of the two trapezoids defined by $math[a, m, f(a), f(m)]\\ 
-and $math[m, b, f(m), f(b)] (where $math[m] is the middle of the interval $ [a, b]$). We can obtain a better approximation by dividing these intervals in two and so on. 
- 
- - Write a function which approximates the integral of a function on an interval. Follow these **steps**: 
- 
-**a)** Write a function which takes a function $math[f] and two points $math[a, b] and calculates the area of the trapezoid $math[a, b, f(a), f(b)]\\ 
- 
-<code haskell> 
- 
-trapezoidArea :: (Double -> Double) -> Double -> Double -> Double 
- 
-</​code>​ 
- 
-**b)** Write a function which takes an ascending list of points and inserts between any two points their middle: 
- 
-<code haskell> 
- 
--- [1, 4, 7, 10, 13] ->[1, 2.5, 4, 5.5, 7, 8.5, 10, 11.5, 13] 
-insertMiddle :: [Double] -> [Double] 
- 
-</​code>​ 
- 
-**c)** Write a function which takes a function $math[f] and a list of points $math[p_0,\ p_1,\ p_2,\ p_3,\ ...] and returns the list containing the areas of trapezoids defined by two consecutive points:\\ 
- 
-<code haskell> 
- 
--- f -> [p0, p1, p2, p3, ...] -> [area p0 p1 f(p0) f(p1), area p1 p2 f(p1) f(p2), area p2 p3 f(p2) f(p3)] 
-consArea :: (Double -> Double) -> [Double] -> [Double] 
- 
-</​code>​ 
- 
-**d)** Write a function which takes a function $math[f] and two points $math[a, b] and approximates $math[\displaystyle \int_{a}^{b} f(x) dx] with **tolerance** ''​e=0.00001'',​ using the previous steps. 
- 
-<code haskell> 
- 
-integralApprox :: (Double -> Double) -> Double -> Double -> Double 
  
 </​code>​ </​code>​