Anuncios

Bienvenidos sean a este post, hoy hablaremos sobre un paradigma de programacion.

Anuncios
Anuncios

Por que es un paradigma? Porque lo podemos considerar como una manera de pensar cuando construimos programas. C++ como cualquier otro lenguaje puede utilizar el programa de procedimiento y ejecutar instrucciones una detras de la otra. Cuando hablamos del enforque orientado a objetos, esta es la descomposicion de un sistema complejo en objetos intercomunicados. En cambio, la programacion funcional apunta a descomponer en funciones en lugar de hacerlo en objetos. Opera con expresiones en lugar de instrucciones.

Anuncios

De una manera muy simple, toma un valor como entrada y lo pasa a la funcion para que este genere una salida, y esta salida es utilizada como entrada para otra funcion. Puede sonar simple, pero la programacion funcional incorpora varias reglas y practicas que pueden dar la sensacion de mucha dificultad. Pero si logras adaptarte a esta manera de pensar, vas a comenzar a pensar en manera funcional. Vamos a analizar este primer ejemplo:

#include <iostream>
#include <vector>

using MatrixInt = std::vector<std::vector<int>>;

std::vector<int> contar_pares(const MatrixInt& num)
{
        std::vector<int> numeros_pares;
        for (const auto& linea : num) {
                int par{0};
                for(const auto& n : linea)
                        if (n % 2 == 0) ++par;
                numeros_pares.push_back(par);
        }
        return numeros_pares;
}

int main()
{
        MatrixInt lista{{1,2,3,4,5,6}};
        lista.push_back({10,20,31,41,50,60});
        lista.push_back({1,3,5,7,9});
        lista.push_back({2,4,6,8,10});
        const auto& pares = contar_pares(lista);
        for(int i = 0; i < lista.size(); i++)
        {
                std::cout << "{ ";
                for(int v : lista[i])
                {
                        std::cout << v << " ";
                }
                std::cout << "} => " << pares[i] << std::endl;
        }

        return 0;
}
Anuncios

Este codigo nos permite contar los numeros pares de un vector en otro vector. Analicemos la primera curiosidad:

using MatrixInt = std::vector<std::vector<int>>;
Anuncios
Anuncios

Esta es otra forma de establecer un alias de tipo, similar a typedef, donde ahora ese tipo equivale al vector dentro de otro vector que almacena valores de tipo int. Lo siguiente es la funcion para contar los numeros pares. Esta devolvera un vector con todos los valores indicando los numeros pares de cada vector interno. Para ello recibiremos al vector que establecimos anteriormente y lo usaremos para procesarlo. El primer objeto sera el utilizado para devolver todos los valores que obtengamos de cada lista. El primer bucle sera para pasar por cada lista, aqui iniciaremos a la variable encargada de almacenar la cantidad de pares que posee y el siguiente bucle pasa por la lista y determinamos cada valor par mediante el operador de modulo. Si este devuelve 0, es indicativo que es par e incrementamos la variable encargada. Una vez terminado el bucle, pasamos a agregar el valor final en el vector que devolveremos. Esto lo repetiremos con todas las listas que posee el vector informado. Una vez finalizado todo el proceso podemos devolver todos los valores que agregamos.

Anuncios
Anuncios

En el main, primero definimos una lista del alias que definimos al inicio, y la iniciamos con algunos valores. Lo siguiente es agregar distintos valores de tipo array mediante push_back en lista. Esto lo haremos tres veces mas, con nuestros valores agregados definimos un objeto de tipo auto y en este almacenaremos el resultado de la funcion anterior y le pasamos la lista que generamos como dato. Luego tenemos un bucle que recuperara cada linea de la lista. En esta mostraremos el contenido de cada lista interna con otro bucle y una vez finalizado mostraremos los numeros pares que posee mediante la variable pares y la pasada del bucle. Esto lo repetiremos hasta finalizar las listas en el vector. Compilemos y veamos como es la salida:

$ ./func
{ 1 2 3 4 5 6 } => 3
{ 10 20 31 41 50 60 } => 4
{ 1 3 5 7 9 } => 0
{ 2 4 6 8 10 } => 5
$
Anuncios

Observen como funciono perfectamente y esto podemos hacerlo con una lista y hasta infinitas listas en el vector. Pero este codigo se puede mejorar un poco, para ello modificaremos el codigo de la siguiente manera:

#include <iostream>
#include <vector>
#include <algorithm>

using MatrixInt = std::vector<std::vector<int>>;

int contador(const std::vector<int>& lineas)
{
        return std::count_if(lineas.begin(), lineas.end(),
                                [](int num){ return num % 2 == 0; });
}

std::vector<int> contar_pares(const MatrixInt& numeros)
{
        std::vector<int> numeros_pares;
        for(const auto& linea : numeros)
        {
                numeros_pares.push_back(contador(linea));
        }
        return numeros_pares;
}

int main()
{
        MatrixInt lista{{1,2,3,4,5,6}};
        lista.push_back({10,20,31,41,50,60});
        lista.push_back({1,3,5,7,9});
        lista.push_back({2,4,6,8,10});
        const auto& pares = contar_pares(lista);
        for(int i = 0; i < lista.size(); i++)
        {
                std::cout << "{ ";
                for(int v : lista[i])
                {
                        std::cout << v << " ";
                }
                std::cout << "} => " << pares[i] << std::endl;
        }

        return 0;
}
Anuncios
Anuncios

Este es muy similar al anterior pero su unica diferencia es la descomposicion de contar_pares en dos funciones. La nueva se llama contador y se encarga de contar los numeros pares en cada vector dentro del vector. Pero lo haremos de una manera particular, para ello usaremos a count_if. Para poder usarlo deben importar a la libreria algorithm. Esta funcion contara solo si se cumple la condicion y para establecer un rango debemos pasar los objetos iteradores de inicio y final del vector en los dos primeros argumentos. En el tercer argumento pasamos la funcion encargada de validar la condicion para cumplirla. Esta puede ser una funcion normal o como en este caso, una funcion lambda. Donde cada valor en el vector lo tomaremos como argumento y le aplicaremos la operacion de modulo para verificar si es par o no, tal como haciamos en el codigo anterior. Cada vez que se cumple y devolvemos un true incrementa el contador y una vez terminado devolvemos el valor final.

Anuncios

Con la parte encargada de contar los numeros pares de un vector en otra funcion, nuestro contador de numeros pares se simplifica. Ahora solamente necesitamos un bucle para recuperar cada vector interno y lo pasamos a la funcion anterior y cada valor devuelto lo asignamos a otro vector que sera el que devolvemos una vez terminada la verificacion. El resto del codigo sigue siendo el mismo, si lo compilan y ejecutan deben obtener el mismo resultado que antes.

Anuncios

Separar grandes problemas en mas pequeños, tareas independientes es el corazon de la programacion funcional. Donde cada funcion esta especializada para realizar una simple tarea sin darse cuenta del problema original. Esto da como resultado que las funciones se componen juntas para generar una coleccion de elementos transformados desde la entrada cruda inicial. En los proximos posts iremos viendo mas temas complementarios a la base de este paradigma.

Anuncios

En resumen, hoy hemos visto a programacion funcional, que es, la base misma de este, un ejemplo para ver como se puede aplicar para facilitar nuestras tareas. Espero les haya resultado de utilidad sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Anuncios
pp258

Donatión

It’s for site maintenance, thanks!

$1.50