{"id":4412,"date":"2014-09-20T05:00:41","date_gmt":"2014-09-20T03:00:41","guid":{"rendered":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/?p=4412"},"modified":"2016-01-09T18:13:47","modified_gmt":"2016-01-09T17:13:47","slug":"iteracion-recursion-y-punto-fijo","status":"publish","type":"post","link":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/iteracion-recursion-y-punto-fijo\/","title":{"rendered":"Iteraci\u00f3n, recursi\u00f3n y punto fijo"},"content":{"rendered":"<p>En esta relaci\u00f3n de ejercicios se muestra c\u00f3mo se pueden transformar programas iterativos (con bucles while o for) en programas en recursivos. Para cada uno de los bucles, se elige una funci\u00f3n y se pide definirla usando el bucle (en Python), buscar una definici\u00f3n recursiva que sea semejante a la anterior, definir el patr\u00f3n que abstrae el bucle, definirla con el patr\u00f3n y aplicar el patr\u00f3n a otras funciones. Finalmente, se estudia c\u00f3mo definir algunas de las anteriores funciones usando el menor punto fijo.<\/p>\n<p><!--more--><\/p>\n<p>La relaci\u00f3n est\u00e1 elaborado como complemento del tema <a href=\"http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-13\/temas\/tema-7.pdf\">Funciones de orden superior<\/a> del curso de <a href=\"http:\/\/www.cs.us.es\/~jalonso\/cursos\/i1m-13\">Inform\u00e1tica<\/a> de primero del Grado en Matem\u00e1ticas.<\/p>\n<h2>El bucle while con un par\u00e1metro<\/h2>\n<p><strong>Nota [Parte impar].<\/strong> Todo n\u00famero entero <code>n<\/code> se puede escribir como <code>m*2^k<\/code>, con <code>m<\/code> impar. Se dice que <code>m<\/code> es la parte impar de <code>n<\/code>. Por ejemplo, la parte impar de 40 es 5 porque 40 = 5*2^3.<\/p>\n<p><strong>Ejercicio 1 [Parte impar con while en Python].<\/strong> Definir en Python, usando un blucle while, la funci\u00f3n <code>parteImpar<\/code> tal que <code>parteImpar(n)<\/code> es la parte impar de <code>n<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef parteImpar(n): \n    while n % 2 == 0:\n        n = n\/2\n    return n\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 2 [Parte impar por recursi\u00f3n].<\/strong> Definir, por recursi\u00f3n, la funci\u00f3n<\/dt>\n<dd>\n<code>parteImpar :: Int -&gt; Int<\/code>\n<\/dd>\n<dt>tal que <code>(parteImpar n)<\/code> es la parte impar de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>parteImpar 40  ==  5<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nparteImpar :: Int -> Int\nparteImpar n | even n    = parteImpar (n `div` 2)\n             | otherwise = n\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 3 [El bucle while1].<\/strong> Definir la funci\u00f3n<\/dt>\n<dd>\n<code>while1 :: (a -&gt; Bool) -&gt; (a -&gt; a) -&gt; a -&gt; a<\/code>\n<\/dd>\n<dt>tal que <code>(while1 p f x)<\/code> es el resultado de aplicar la funci\u00f3n <code>f<\/code> a <code>x<\/code> mientras cumple la propiedad <code>p<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>while1 (&lt;1000) (*2) 1  ==  1024<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (por recursi\u00f3n):\nwhile1 :: (a -> Bool) -> (a -> a) -> a -> a\nwhile1 p f x | p x       = while1 p f (f x)\n             | otherwise = x\n\n-- 2\u00aa definici\u00f3n (con until):\nwhile1b :: (a -> Bool) -> (a -> a) -> a -> a\nwhile1b p f x = until (not . p) f x\n\n-- 3\u00aa definici\u00f3n (con until y composici\u00f3n):\nwhile1c :: (a -> Bool) -> (a -> a) -> a -> a\nwhile1c = until . (not.)\n<\/pre>\n<p><strong>Ejercicio 4 [Parte impar con el bucle while1].<\/strong> Redefinir, usando <code>while1<\/code>, la funci\u00f3n <code>parteImpar<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nparteImpar2 :: Int -> Int\nparteImpar2 = while1 even (`div` 2)\n<\/pre>\n<p><strong>Nota [La \u00f3rbita de Collatz].<\/strong> El sucesor de Collatz de un n\u00famero <code>n<\/code> es <code>n\/2<\/code>, si <code>n<\/code> es par y <code>3n+1<\/code> , en caso contrario. La \u00f3rbita de un n\u00famero se obtiene escribiendo los sucesivos sucesores de Collatz hasta llegar a 1. Por ejemplo, la \u00f3rbita de Collatz de 7 es 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1.<\/p>\n<dl>\n<dt><strong>Ejercicio 5 [La \u00f3rbita de Collatz con while en Python].<\/strong> Definir en Python, usando <code>while<\/code>, la funci\u00f3n <code>collatz<\/code> tal que <code>collatz(n)<\/code> es la \u00f3rbita de Collatz de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>collatz(7) == [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef collatz(n):\n    s = [n]\n    while (n != 1):\n        if n % 2 == 0:\n            n = n\/\/2\n        else:\n            n = 3*n+1\n        s.append(n)\n    return s\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 6 [La \u00f3rbita de Collatz por recursi\u00f3n].<\/strong> Definir, mediante recursi\u00f3n, la funci\u00f3n<\/dt>\n<dd>\n<code>collatz :: Integer -&gt; [Integer]<\/code>\n<\/dd>\n<dt>tal que (collatz n) es la \u00f3rbita de Collatz de n. Por ejemplo,<\/dt>\n<dd>\n<code>collatz 7 == [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (con condicionales):\ncollatz :: Integer -> [Integer]\ncollatz n = reverse (aux [n])\n    where aux (n:ns) = if n == 1 then n:ns\n                       else if even n \n                            then aux (div n 2:n:ns)\n                            else aux (3*n+1:n:ns)\n\n-- 2\u00aa definici\u00f3n (con guardas):\ncollatz2 :: Integer -> [Integer]\ncollatz2 n = reverse (aux [n])\n    where aux (1:ns) = 1:ns\n          aux (n:ns) | even n    = aux (div n 2:n:ns)\n                     | otherwise = aux (3*n+1:n:ns)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 7 [La \u00f3rbita de Collatz con while1].<\/strong> Definir, usando <code>while1<\/code>, la<\/dt>\n<dt>funci\u00f3n<\/dt>\n<dd>\n<code>collatz :: Integer -&gt; [Integer]<\/code>\n<\/dd>\n<dt>tal que <code>(collatz n)<\/code> es la \u00f3rbita de Collatz de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>collatz 7  ==  [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\ncollatz :: Int -> [Int]\ncollatz n = reverse (aux [n]) where\n    aux = while1 (\\(n:ns) -> n \/= 1)\n                 (\\(n:ns) -> if even n \n                             then (n `div` 2):n:ns \n                             else (3*n+1):n:ns)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 8 [El menor punto fijo por recursi\u00f3n].<\/strong>  Definir, por recursi\u00f3n, la funci\u00f3n<\/dt>\n<dd>\n<code>mpf :: Eq a =&gt; (a -&gt; a) -&gt; a -&gt; a<\/code>\n<\/dd>\n<dt>tal que <code>(mpf f x)<\/code> es el menor punto fijo de <code>f<\/code> respecto de <code>x<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>mpf (\\x -&gt; if x &lt; 10 then x else (div x 10)) 325 == 3<\/code>\n<\/dd>\n<dd><code>mpf (\\x -&gt; if even x then (div x 2) else x) 24 == 3<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nmpf :: Eq a => (a -> a) -> a -> a\nmpf f x | f x == x  = x\n        | otherwise = mpf f (f x)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 9 [El menor punto fijo con while1].<\/strong> Definir, con <code>while1<\/code>, la funci\u00f3n<\/dt>\n<dd>\n<code>mpf :: Eq a =&gt; (a -&gt; a) -&gt; a -&gt; a<\/code>\n<\/dd>\n<dt>tal que <code>(mpf f x)<\/code> es el menor punto fijo de <code>f<\/code> respecto de <code>x<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>mpf (\\x -&gt; if x &lt; 10 then x else (div x 10)) 325 == 3<\/code>\n<\/dd>\n<dd><code>mpf (\\x -&gt; if even x then (div x 2) else x) 24 == 3<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nmpf :: Eq a => (a -> a) -> a -> a\nmpf f = while1 (\\x -> f x \/= x) (\\x -> f x)\n<\/pre>\n<h2>El bucle while con dos par\u00e1metros<\/h2>\n<dl>\n<dt><strong>Ejercicio 10 [Suma impares con bucle while en Python].<\/strong> Definir en Python, usando un bucle <code>while<\/code>, la funci\u00f3n <code>sumaImpares<\/code> tal que <code>sumaImpares(n)<\/code> es la suma de los <code>n<\/code> primeros n\u00fameros impares. Por ejemplo,<\/dt>\n<dd>\n<code>sumaImpares(3)  ==  9<\/code>\n<\/dd>\n<dd><code>sumaImpares(4)  ==  16<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef sumaImpares(n): \n    s = 0\n    k = 0\n    while k < n:\n        s = s + 2*k + 1\n        k = k + 1\n    return s\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 11 [Suma impares por recursi\u00f3n].<\/strong> Definir en Haskell la funci\u00f3n<\/dt>\n<dd>\n<code>sumaImpares :: Int -&gt; Int<\/code>\n<\/dd>\n<\/dl>\n<p>que traduzca la definici\u00f3n anterior.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n\nsumaImpares :: Int -> Int\nsumaImpares n = aux n 0 0 where\n    aux n k s = if k < n then \n                    let s1 = s + 2*k + 1\n                        k1 = k + 1\n                    in aux n k1 s1 \n                else s\n\n-- 2\u00aa definici\u00f3n (usando where en lugar de let)\nsumaImpares2 :: Int -> Int\nsumaImpares2 n = aux n 0 0 where\n    aux n k s = if k < n \n                then aux n k1 s1  \n                else s\n                where s1 = s + 2*k + 1\n                      k1 = k + 1\n\n-- 3\u00aa definici\u00f3n (sin let ni where)\nsumaImpares3 :: Int -> Int\nsumaImpares3 n = aux n 0 0 where\n    aux n k s = if k < n \n                then aux n (k + 1) (s + 2*k + 1)\n                else s\n\n-- 4\u00aa definici\u00f3n (con guardas)\nsumaImpares4 :: Int -> Int\nsumaImpares4 n = aux n 0 0 where\n    aux n k s | k < n     = aux n (k + 1) (s + 2*k + 1)\n              | otherwise = s\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 12 [El bucle while2]<\/strong> Definir la funci\u00f3n<\/dt>\n<dd>\n<code>while2 :: (a -&gt; b -&gt; Bool) -&gt; (a -&gt; b -&gt; (a,b)) -&gt; a -&gt; b -&gt; b<\/code>\n<\/dd>\n<dt>tal que <code>(while2 p f x y)<\/code> aplica <code>f<\/code> a <code>x<\/code> e <code>y<\/code> mientras que se cumple la propiedad <code>p<\/code> y devuelve <code>y<\/code> cuando no se cumple. Por ejemplo,<\/dt>\n<dd>\n<code>(while2 (\\x y -&gt; x&lt;3) (\\x y -&gt; (x+1,x+y))) 0 0  ==  3<\/code>\n<\/dd>\n<dd><code>(while2 (\\x y -&gt; x&lt;4) (\\x y -&gt; (x+1,x+y))) 0 0  ==  6<\/code><\/dd>\n<\/dl>\n<p>El procedimiento de evaluaci\u00f3n de <code>(while2 p f x y)<\/code> es el siguiente<\/p>\n<ul>\n<li>si se verifica <code>(p x y)<\/code>, eval\u00faa <code>(f x y)<\/code> que dar\u00e1 un par <code>(x1,y1)<\/code><\/li>\n<li>si se verifica <code>(p x1 y1)<\/code>, eval\u00faa <code>(f x1 y1)<\/code> que dar\u00e1 un par <code>(x2,y2)<\/code><\/li>\n<li>y as\u00ed hasta que llegue a un par <code>(xn,yn)<\/code> tal que no se verifique <code>(p xn yn)<\/code>, en cuyo caso devuelve <code>yn<\/code>.<\/li>\n<\/ul>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nwhile2 :: (a -> b -> Bool) -> (a -> b -> (a,b)) -> a -> b -> b\nwhile2 p f x y \n    | p x y     = while2 p f x1 y1\n    | otherwise = y \n    where (x1,y1) = f x y\n<\/pre>\n<p><strong>Ejercicio 13 [Suma impares con while2].<\/strong>  Redefinir, usando <code>while2<\/code>, la funci\u00f3n <code>sumaImpares<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nsumaImpares :: Int -> Int\nsumaImpares n = aux n 0 0 where\n    aux n = while2\n             (\\k s -> k < n)\n             (\\k s -> (k+1,s+2*k+1))\n<\/pre>\n<p><strong>Ejercicio 14 [El algoritmo de Euclides con while en Python].<\/strong> Definir en Python la funci\u00f3n <code>mcd<\/code> tal que <code>mcd(x,y)<\/code> es el m\u00e1ximo com\u00fan divisor de <code>x<\/code> e <code>y<\/code>, calculado mediante el algoritmo de Euclides.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef mcd(x,y):\n    while x != y:\n        if x > y: \n            x = x - y \n        else: \n            y = y - x\n    return y\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 15 [El algoritmo de Euclides por recursi\u00f3n].<\/strong> Definir la funci\u00f3n<\/dt>\n<dd>\n<code>mcd :: Int -&gt; Int -&gt; Int<\/code>\n<\/dd>\n<\/dl>\n<p>tal que <code>mcd(x,y)<\/code> es el m\u00e1ximo com\u00fan divisor de <code>x<\/code> e <code>y<\/code>, calculado mediante el algoritmo de Euclides.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nmcd :: Int -> Int -> Int\nmcd x y | x \/= y    = if x > y \n                      then mcd (x-y) y\n                      else mcd x (y-x)\n        | otherwise = y\n<\/pre>\n<p><strong>Ejercicio 16 [El algoritmo de Euclides con while2].<\/strong> Redefinir, usando <code>while2<\/code>, la funci\u00f3n <code>mcd<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nmcd2 :: Int -> Int -> Int\nmcd2 = while2 \n       (\\ x y -> x \/= y) \n       (\\ x y -> if x > y \n                 then (x-y,y) \n                 else (x,y-x))\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 17 [El factorial con while en Python].<\/strong> Definir en Python, usando <code>while<\/code>, la funci\u00f3n <code>fact<\/code> tal que <code>fact(n)<\/code> es el factorial de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>fact(4)  ==  24<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef factorial(n):\n    f = 1\n    while n != 0:\n        f = f*n\n        n = n-1\n    return f\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 18 [El factorial por recursi\u00f3n].<\/strong> Definir, por recursi\u00f3n, la funci\u00f3n<\/dt>\n<dd>\n<code>fact :: Integer -&gt; Integer<\/code>\n<\/dd>\n<dt>tal que <code>(fact n)<\/code> es el factorial de `n. Por ejemplo,<\/dt>\n<dd>\n<code>fact 4  ==  24<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (con acumulador):\nfactorial :: Integer -> Integer\nfactorial n = aux n 1\n    where aux 0 f = f\n          aux n f = aux (n-1) (n*f)\n\n-- 2\u00aa definici\u00f3n (sin acumulador):\nfactorial2 :: Integer -> Integer\nfactorial2 0 = 1\nfactorial2 n = n * factorial2 (n-1)\n<\/pre>\n<p><strong>Ejercicio 19 [El factorial con while2].<\/strong> Redefinir, con <code>while2<\/code>, la funci\u00f3n <code>fact<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (con auxiliar):\nfactorial :: Integer -> Integer\nfactorial n = aux n 1\n    where aux = while2 (\\n f -> n \/= 0)\n                       (\\n f -> (n-1,f*n))\n\n-- 2\u00aa definici\u00f3n (sin auxiliar):\nfactorial2 :: Integer -> Integer\nfactorial2 n = (while2 (\\n f -> n \/= 0)\n                       (\\n f -> (n-1,f*n))) n 1\n<\/pre>\n<h2>El bucle while con tres par\u00e1metros<\/h2>\n<dl>\n<dt><strong>Ejercicio 20 [Fibonacci con while en Python].<\/strong> Definir la funci\u00f3n <code>fib<\/code> tal que <code>fib(n)<\/code> es el <code>n<\/code>-\u00e9simo t\u00e9rmino de la sucesi\u00f3n de Fibonacci. Por ejemplo,<\/dt>\n<dd>\n<code>[fib(n) for n in range(10)]  ==  [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\n# 1\u00aa definici\u00f3n\ndef fib(n):\n    x = 0\n    y = 1\n    while (n != 0):\n        x, y = (y,x+y)\n        n = n-1\n    return x\n\n# 2\u00aa definici\u00f3n\ndef fib2(n):\n    if n == 0:\n        return 0\n    else: \n        x = 0\n        y = 1\n        while (n > 1):\n            x, y = (y,x+y)\n            n = n-1\n        return y\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 21 [Fibonacci por recursi\u00f3n].<\/strong> Definir, por recursi\u00f3n, la funci\u00f3n<\/dt>\n<dd>\n<code>fib :: Int -&gt; Int<\/code>\n<\/dd>\n<dt>tal que <code>(fib n)<\/code> es el <code>n<\/code>-\u00e9simo t\u00e9rmino de la sucesi\u00f3n de Fibonacci. Por ejemplo,<\/dt>\n<dd>\n<code>[fib n | n &lt;- [0..9]]  ==  [0,1,1,2,3,5,8,13,21,34]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (semejante a la iterativa con while)\nfib :: Int -> Int\nfib 0 = 0\nfib n = aux (n-1) 0 1 where\n    aux 0 x y = y\n    aux n x y = aux (n-1) y (x+y)\n\n-- 2\u00aa definici\u00f3n:\nfib2 :: Int -> Int\nfib2 n = aux n 0 1 where\n     aux 0 x y = x\n     aux n x y = aux (n-1) y (x+y)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 22 [El bucle while3].<\/strong> Definir la funci\u00f3n<\/dt>\n<dd>\n<code>while3 :: (a -&gt; b -&gt; c -&gt; Bool) -&gt; (a -&gt; b -&gt; c -&gt; (a,b,c)) -&gt; a -&gt; b -&gt; c<\/code> -> c`\n<\/dd>\n<dt>tal que <code>(while3 p f x y z)<\/code> es una generalizaci\u00f3n de <code>while2<\/code> con tres par\u00e1metros. Por ejemplo,<\/dt>\n<dd>\n<code>while3 (\\n x y -&gt; n &gt; 0)(\\n x y -&gt; (n-1,y,x+y)) 5 0 1 == 8<\/code>\n<\/dd>\n<dd><code>while3 (\\n x y -&gt; n &gt; 0)(\\n x y -&gt; (n-1,y,x+y)) 6 0 1 == 13<\/code><\/dd>\n<dd><code>while3 (\\n x y -&gt; n &gt; 0)(\\n x y -&gt; (n-1,y,x+y)) 7 0 1 == 21<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nwhile3 :: (a -> b -> c -> Bool)\n       -> (a -> b -> c -> (a,b,c))\n       -> a -> b -> c -> c\nwhile3 p f x y z \n    | p x y z   = while3 p f x1 y1 z1\n    | otherwise = z \n    where (x1,y1,z1) = f x y z \n<\/pre>\n<p><strong>Ejercicio 23 [Fibonacci con while3].<\/strong> Redefinir, con <code>while3<\/code>, la funci\u00f3n <code>fib<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nfib :: Int -> Int\nfib 0 = 0\nfib n = aux (n-1) 0 1 where\n    aux = while3 (\\n x y -> n \/= 0)\n                 (\\n x y -> (n-1,y,x+y))\n<\/pre>\n<h2>El bucle for con un par\u00e1metro<\/h2>\n<dl>\n<dt><strong>Ejercicio 24 [El factorial con for en Python].<\/strong> Definir en Python, usando <code>for<\/code>, la funci\u00f3n <code>fact<\/code> tal que <code>fact(n)<\/code> es el factorial de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>fact(4)  ==  24<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\ndef factorial(n):\n    f = 1\n    for k in range(1,n+1):\n        f = k*f\n    return f\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 25 [El bucle for].<\/strong> Definir la funci\u00f3n<\/dt>\n<dd>\n<code>for :: [a] -&gt; (a -&gt; b -&gt; b) -&gt; b -&gt; b<\/code>\n<\/dd>\n<dt>tal que <code>(for xs f y)<\/code> es el resultado de iterar <code>f<\/code> sobre los elementos de <code>xs<\/code> a partir de <code>y<\/code>; es decir, si <code>xs<\/code> es <code>[x(1),...,x(n)]<\/code> entonces <code>(for xs f y)<\/code> es <code>(f x(n) (f x(n-2) (... (f x(2) (f x(1) y)))))<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>(for [1..4] (\\x s -&gt; x+s)) 0 == 10<\/code>\n<\/dd>\n<dd><code>(for [1..4] (\\x s -&gt; x*s)) 1 ==  24<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\n-- 1\u00aa definici\u00f3n (por recursi\u00f3n):\nfor :: [a] -> (a -> b -> b) -> b -> b\nfor []     f y = y\nfor (x:xs) f y = for xs f (f x y)\n\n-- 2\u00aa definici\u00f3n (por plegado):\nforP :: [a] -> (a -> b -> b) -> b -> b\nforP xs f y = foldr f y xs\n<\/pre>\n<p><strong>Ejercicio 26 [El factorial con for].<\/strong> Reefinir, usando <code>for<\/code>, la funci\u00f3n <code>fact<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nfact :: Integer -> Integer\nfact n = for [1..n] (\\ k f -> k*f) 1 \n<\/pre>\n<h2>El bucle for con dos par\u00e1metros<\/h2>\n<dl>\n<dt><strong>Ejercicio 27 [Fibonacci con for en Python].<\/strong> Definir en Python, usando <code>for<\/code>, la funci\u00f3n <code>fib<\/code> tal que <code>fib(n)<\/code> es el <code>n<\/code>-\u00e9simo t\u00e9rmino de la sucesi\u00f3n de Fibonacci. Por ejemplo,<\/dt>\n<dd>\n<code>[fib(n) for n in range(10)]  ==  [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"python\">\n# 1\u00aa definici\u00f3n\ndef fib(n):\n    x = 0\n    y = 1\n    for k in range(n):\n        x, y = (y,x+y)\n    return x\n\n# 2\u00aa definici\u00f3n\ndef fib2(n):\n    if n == 0:\n        return 0\n    else:\n        x = 0\n        y = 1\n        for k in range(1,n):\n            x, y = (y,x+y)\n        return y\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 28 [El bucle for2].<\/strong> Definir el bucle <code>for<\/code> con 2 par\u00e1metros. Por ejemplo.<\/dt>\n<dd>\n<code>for2 [1..9] (\\x y z -&gt; (x+y,y:z)) 0 []  ==  [36,28,21,15,10,6,3,1,0]<\/code>\n<\/dd>\n<dd><code>for2 [1..7] (\\x y z -&gt; (x*y,y:z)) 1 []  ==  [720,120,24,6,2,1,1]<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nfor2 :: [a] -> (a -> b -> c -> (b,c)) -> b -> c -> c\nfor2 []     f _ z = z\nfor2 (x:xs) f y z = for2 xs f y1 z1\n    where (y1,z1) = f x y z \n<\/pre>\n<p><strong>Ejercicio 29 [Fibonacci con for2].<\/strong> Redefinir, con <code>for2<\/code>, la funci\u00f3n <code>fib<\/code>.<\/p>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nfib :: Int -> Int\nfib 0 = 0\nfib n = aux (n-1) 0 1 where\n    aux n = for2 [1..n] (\\k x y -> (y,x+y))\n<\/pre>\n<h2>Recursi\u00f3n y puntos fijos<\/h2>\n<p><strong>Nota.<\/strong> En esta secci\u00f3n se proponen ejercicios para eliminar la recursi\u00f3n mediante puntos fijos; en concreto, usando la funci\u00f3n <code>fix<\/code> tal que <code>(fix f)<\/code> es el menor punto fijo de <code>f<\/code>. La funci\u00f3n <code>fix<\/code> est\u00e1 definida en la librer\u00eda <code>Data.Function<\/code> como<\/p>\n<pre lang=\"haskell\">\nfix :: (a -> a) -> a\nfix f = f (fix f)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 30 [Factorial mediante fix].<\/strong> Definir, usando <code>fix<\/code>, la funci\u00f3n<\/dt>\n<dd>\n<code>fact :: Integer -&gt; Integer<\/code>\n<\/dd>\n<dt>tal que <code>(fact n)<\/code> es el factorial de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>[fact n | n &lt;- [0..6]]  ==  [1,1,2,6,24,120,720]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nimport Data.Function (fix)\n\n-- 1\u00aa definici\u00f3n (con auxiliar)\nfact :: Integer -> Integer\nfact = fix aux\n\naux :: (Integer -> Integer) -> Integer -> Integer\naux f n = if n == 0 then 1 else n * f (n-1)\n\n-- C\u00e1lculo de (fact 3)\n--    fact 3 =\n--    = (fix aux) 3\n--    = aux (fix aux) 3\n--    = 3 * ((fix aux) 2)\n--    = 3 * (aux (fix aux) 2)\n--    = 3 * (2 * ((fix aux) 1))\n--    = 3 * (2 * ((fix aux) 1))\n--    = 3 * (2 * (aux (fix aux) 1))\n--    = 3 * (2 * (1 * ((fix aux) 0)))\n--    = 3 * (2 * (1 * 1))\n--    = 6\n\n-- 2\u00aa definici\u00f3n (sin auxiliar)\nfact2 :: Integer -> Integer\nfact2 = fix (\\f n -> if n == 0 then 1 else n * f (n-1))\n\n-- Nota. Puesto que fact es punto fijo de aux, se tiene\n--    fact = aux fact\n--         = (\\f n -> if n == 0 then 1 else n * f (n-1)) fact\n--         = \\n -> if n == 0 then 1 else n * fact (n-1)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 31 [Fibonacci mediante fix].<\/strong> Definir, usando <code>fix<\/code>, la funci\u00f3n<\/dt>\n<dd>\n<code>fib :: Int -&gt; Int<\/code>\n<\/dd>\n<dt>tal que <code>(fib n)<\/code> es el <code>n<\/code>-\u00e9simo t\u00e9rmino de la sucesi\u00f3n de Fibonacci. Por ejemplo,<\/dt>\n<dd>\n<code>[fib n | n &lt;- [0..9]]  ==  [0,1,1,2,3,5,8,13,21,34]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nimport Data.Function (fix)\n\n-- 1\u00aa definici\u00f3n (con auxiliares)\nfib :: Int -> Int\nfib = fibAux 0 1 where\n    fibAux      = fix aux \n    aux f x y n = if n == 0 then x else f y (x+y) (n-1)\n\n-- C\u00e1lculo de (fib 6)\n--    fib 6\n--    = fibAux 0 1 6\n--    = (fix aux) 0 1 6\n--    = aux (fix aux) 0 1 6\n--    = (fix aux) 1 1 5\n--    = aux (fix aux) 1 1 5\n--    = (fix aux) 1 2 4\n--    = aux (fix aux) 1 2 4\n--    = (fix aux) 2 3 3\n--    = aux (fix aux) 2 3 3\n--    = (fix aux) 3 5 2\n--    = aux (fix aux) 3 5 2\n--    = (fix aux) 5 8 1\n--    = aux (fix aux) 8 13 0\n--    = 8\n\n-- 2\u00aa definici\u00f3n (sin auxiliares):\nfib2 :: Int -> Int\nfib2 = (fix (\\f x y n -> if n == 0 then x else f y (x+y) (n-1))) 0 1\n\n-- Nota. Puesto que fibAux es punto fijo de aux, se tiene\n--    fibAux = aux fibAux\n--           = (\\f x y n -> if n == 0 then x else f y (x+y) (n-1)) fibAux \n--           = \\x y n -> if n == 0 then x else fibAux y (x+y) (n-1) \n<\/pre>\n<dl>\n<dt><strong>Ejercicio 32 [La \u00f3rbita de Collatz mediante fix].<\/strong> Definir, usando <code>fix<\/code>, la funci\u00f3n<\/dt>\n<dd>\n<code>collatz :: Integer -&gt; [Integer]<\/code>\n<\/dd>\n<dt>tal que <code>(collatz n)<\/code> es la \u00f3rbita de Collatz de <code>n<\/code>. Por ejemplo,<\/dt>\n<dd>\n<code>collatz 7  ==  [7,22,11,34,17,52,26,13,40,20,10,5,16,8,4,2,1]<\/code>\n<\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nimport Data.Function (fix)\n\n-- 1\u00aa definici\u00f3n (con auxiliares):\ncollatz :: Integer -> [Integer]\ncollatz n = reverse (collatzAux [n]) where\n    collatzAux   = fix aux\n    aux f (n:ns) = if n == 1 \n                   then n:ns\n                   else if even n \n                        then f (div n 2:n:ns)\n                        else f (3*n+1:n:ns)\n\n-- 2\u00aa definici\u00f3n (sin auxiliares):\ncollatz2 :: Integer -> [Integer]\ncollatz2 n = \n   reverse ((fix (\\f (n:ns) -> if n == 1 \n                               then n:ns\n                               else if even n \n                                    then f (div n 2:n:ns)\n                                    else f (3*n+1:n:ns)))\n            [n])\n\n-- Nota: Puesto que collatzAux es un punto fijo de aux, se tiene\n--    collatzAux = aux collatzAux\n--               = (\\f (n:ns) -> if n == 1 \n--                               then n:ns\n--                               else if even n \n--                                    then f (div n 2:n:ns)\n--                                    else f (3*n+1:n:ns)) collatzAux\n--               = \\(n:ns) -> if n == 1 \n--                            then n:ns\n--                            else if even n \n--                                 then collatzAux (div n 2:n:ns)\n--                                 else collatzAux (3*n+1:n:ns)\n<\/pre>\n<dl>\n<dt><strong>Ejercicio 33 [Suma impares mediante fix].<\/strong> Definir, usando <code>fix<\/code>, la funci\u00f3n<\/dt>\n<dd>\n<code>sumaImpares :: Int -&gt; Int<\/code>\n<\/dd>\n<dt>tal que <code>(sumaImpares n)<\/code> es la suma de los primeros <code>n<\/code> n\u00fameros impares. Por ejemplo,<\/dt>\n<dd>\n<code>sumaImpares 3  ==  9<\/code>\n<\/dd>\n<dd><code>sumaImpares 4  ==  16<\/code><\/dd>\n<\/dl>\n<p><em>Soluci\u00f3n:<\/em><\/p>\n<pre lang=\"haskell\">\nimport Data.Function (fix)\n\nsumaImpares :: Int -> Int\nsumaImpares n = sumaImparesAux n 0 0 where\n    sumaImparesAux = fix aux\n    aux f n k s | k < n     = f n (k + 1) (s + 2*k + 1)\n                | otherwise = s\n<\/pre>\n<h2>Referencias<\/h2>\n<ul>\n<li>A.V. Aho y J.D. Ullman. <a href=\"http:\/\/stanford.io\/1rXXLNF\">Iteration, induction, and recursion<\/a>. Cap\u00edtulo 2 de <a href=\"http:\/\/infolab.stanford.edu\/~ullman\/focs.html\">Foundations of Computer Science<\/a>.<\/li>\n<li>H. Lee <a href=\"http:\/\/harold.hotelling.net\/gcdfix.lhs\">An introduction to fixpoint in Haskell<\/a>.<\/li>\n<li>J. van Eijck. <a href=\"http:\/\/bit.ly\/1tbBJXS\">Functional imperative style<\/a>. Cap\u00edtulo 2 de <a href=\"http:\/\/homepages.cwi.nl\/~jve\/courses\/esslli12\/PFAScourse.pdf\">Purely functional algorithm specification<\/a>.<\/li>\n<li>Wikibooks. <a href=\"http:\/\/bit.ly\/1khqF8X\">Haskell\/Fix and recursion<\/a>.<\/li>\n<li>Wikipedia. <a href=\"http:\/\/bit.ly\/1mYvT3Z\">For loop<\/a><\/li>\n<li>Wikipedia. <a href=\"http:\/\/bit.ly\/1mYwClG\">While loop<\/a>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>En esta relaci\u00f3n de ejercicios se muestra c\u00f3mo se pueden transformar programas iterativos (con bucles while o for) en programas en recursivos. Para cada uno de los bucles, se elige una funci\u00f3n y se pide definirla usando el bucle (en Python), buscar una definici\u00f3n recursiva que sea semejante a la anterior, definir el patr\u00f3n que&#8230;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"footnotes":"","_jetpack_memberships_contains_paid_content":false},"categories":[5],"tags":[270],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"_links":{"self":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4412"}],"collection":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/comments?post=4412"}],"version-history":[{"count":28,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4412\/revisions"}],"predecessor-version":[{"id":5267,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/posts\/4412\/revisions\/5267"}],"wp:attachment":[{"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/media?parent=4412"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/categories?post=4412"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.glc.us.es\/~jalonso\/vestigium\/wp-json\/wp\/v2\/tags?post=4412"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}