Mostrando las entradas con la etiqueta Algoritmos. Mostrar todas las entradas
Mostrando las entradas con la etiqueta Algoritmos. Mostrar todas las entradas

15 de diciembre de 2020

Hilos.

   En un enfoque tradicional de programación, las sentencias y expresiones se ejecutan de manera secuencial, en la programación concurrente, este mismo grupo de sentencias y expresiones se ejecutan de manera concurrente, entendiéndose por concurrencia a la capacidad de las diferentes partes o unidades de un programa para ejecutarse fuera de orden o en orden parcial sin afectar el resultado final.

   Abusando de la simplificación, puede entenderse a la concurrencia como la capacidad de un software o equipo de cómputo para realizar más de una tarea al mismo tiempo.

   En la programación concurrente existen dos unidades básicas de ejecución: procesos e hilos. En el lenguaje de programación Java la programación concurrente se basa principalmente en hilos (threads) aunque estos están estrechamente relacionados con los procesos.

    Los detalles y aspectos relacionados con los procesos gestionados por un sistema operativo quedan fuera de los alcances de este blog; sin embargo, es preciso que el lector tenga al menos una idea general de los aspectos inherentes relacionados con los procesos, razón por la cual se esbozarán algunos conceptos.

   Un proceso es una instancia en ejecución de un programa. En este sentido, un proceso es un entorno de ejecución autocontenido y habitualmente tiene un conjunto de recursos completos, privados, básicos y fundamentales relacionados con su ejecución; así, cada proceso tiene además su propio espacio de memoria.

   Los hilos son también llamados procesos ligeros. Tanto los hilos como los procesos proveen un entorno de ejecución sin embargo, la creación de un nuevo hilo requiere en lo general de menos recursos que la creación de un nuevo proceso.

Programación con hilos.

   Los hilos habitualmente existen dentro de un proceso. Cada proceso tiene al menos un hilo denominado hilo principal. Los hilos comparten los recursos asignados al proceso, tales como la memoria y los archivos asociados por ejemplo, lo cual los hace muy eficientes pero potencialmente problemáticos.

   Desde el punto de vista de los programadores de aplicaciones Java, todo inicia con un solo hilo: main, y este hilo tiene la capacidad de crear nuevos hilos y a partir de ahí generar una programación concurrente a través de dichos hilos.

   Cada hilo en Java está asociado con una instancia de la clase Thread por lo que se recomienda ampliamente al lector revisar la especificación de dicha clase en el API y todo el apartado relacionado con la concurrencia de los tutoriales de Java.

By Hooman Mallahzadeh - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=100534098


3 de abril de 2017

Ejercicios selectos (pilas).

  1. En el Ejemplo PilaPrimitiva el método imprime tiene las líneas 50 y 52 como comentarios ¿Qué sucede si sustituye la línea 51 por la línea 50 y la línea 53 por la línea 52? ¿Compilará? ¿Si sí por qué, y si no por qué? Si compila ¿Cuál será el resultado de la ejecución? Determine sus respuestas y después corrobore las mismas con la experimentación.
  2.  Con base en el Ejemplo PilaPrimitiva, haga una implementación completa de una pila que almacene char primitivos y pruébela Cuando termine, considere lo siguiente:
    1. ¿Puede visualizar las implicaciones de este ejercicio?
    2. ¿Qué pasa por ejemplo si ahora se necesita almacenar datos de tipo double?
  3. En el Ejemplo PruebaPila se creó una pila utilizando un constructor sin argumentos. Modifique dicho ejemplo para asignar un nuevo nombre a la pila por medio del constructor correspondiente; asígnele a la pila el nombre de "Mi primera pila", recompile y pruebe su funcionamiento.
  4. Modifique el Ejemplo PruebaPila para que permita leer n números enteros desde la entrada estándar y los almacene en la Pila.
  5. En el blog, durante la explicación del Ejemplo PruebaPila, se menciona la cláusula try-catch-finally; sin embargo, en dicho ejemplo sólo se muestra el uso de la cláusula try-catch. Investigue y documéntese acerca del uso y funcionamiento de la cláusula completa try-catch-finally. También investigue más acerca del uso y manejo de excepciones, así como la documentación del API respecto al método printStackTrace.
  6. Modifique el Ejemplo Pila para que:
    1. Agregue el método peek a la implementación. Recuerde que dicha operación hecha un vistazo al elemento que se encuentra en el tope de la pila y lo regresa, pero no lo elimina.
    2. Incorpore un atributo privado numérico (n) que lleve el control del número de elementos insertados en la pila. Al respecto no olvide:
      1. Inicializar explícitamente dicho atributo a cero en el constructor.
      2. Proporcionar únicamente el método de tipo get para el atributo n: size( ).
  7. Tomando como referencia el Ejemplo PruebaPilaGenerica, modifíquelo para que la pila genérica del Ejemplo Pila almacene otro tipo de objetos además de los de la clase Integer. Pruebe con al menos las siguientes clases:
    1. Double.
    2. String.
    3. Persona (del Ejemplo Persona).
    4. Cientifico (del Ejemplo Cientifico).
  8. Utilice una pila para verificar si, dada una expresión, ésta es o no un palíndromo. Un palíndromo es una frase o expresión que se lee o interpreta igual procesándola de izquierda a derecha, que de derecha a izquierda. Algunos ejemplos de palíndromos son (Nota: Simplifique el problema y no considere acentos ni la letra ñ en su implementación):
    1. 1991.
    2. 2002.
    3. Hannah.
    4. Reconocer.
    5. Se van sus naves.
    6. Ateo por Arabia iba raro poeta.
    7. Dábale arroz a la zorra el abad.
    8. Anita lava la tina.
    9. La ruta nos aportó otro paso natural.
    10. Las Nemocón no comen sal.
    11. No di mi decoro, cedí mi don.
    12. A la catalana banal, atácala.
  9. Realice la implementación del Algoritmo de verificación de balanceo presentado en la entrada Algunas aplicaciones de las pilas. Para lo anterior, construya una clase cuyo nombre sea Expresion, e implemente dicho algoritmo como uno de los servicios o acciones de la clase, identifique al método como verificaBalance de tal forma que su firma sea: public boolean verificaBalance( );.
    1. No olvide realizar las pruebas correspondientes para validar y verificar la funcionalidad de su propuesta.
    2. Sugerencia: implemente la verificación de equivalencia de símbolos como un método privado; es decir, un método que proporcione servicio a otros métodos de la misma clase (servicio interno), pero no a los objetos instanciados (servicios públicos).
  10. Convierta paso a paso utilizando papel y lápiz, las siguientes expresiones en su representación en interfija a su correspondiente notación postfija. Nota: el símbolo @ representa la potencia y es el de mayor precedencia. Note que se han proporcionado las soluciones correspondientes:
    1. A + B.
      1. A B +.
    2. A + B - C.
      1. A B + C -.
    3. (A + B) * (C - D).
      1. A B + C D - *.
    4. A @ B * C – D + E / F / (G + H).
      1. A B @ C * D - E F / G H + / +.
    5. ((A + B) * C – (D - E)) @ ( F + G).
      1. A B + C * D E - - F G + @.
    6. A – B / (C * D @ E).
      1. A B C D E @ * / -.
  11. Continuando con la idea planteada en el ejercicio anterior, convierta paso a paso las expresiones pero ahora a su representación en notación prefija. Se proporcionan a continuación las soluciones correspondientes:
    1. + A B.
    2. - + A B C.
    3. * + A B - C D.
    4. + - * @ A B C D / / E F + G H.
    5. @ - * + A B C - D E + F G.
    6. - A / B * C @ D E.
  12. Diseñe un algoritmo, así como su correspondiente implementación, para convertir una expresión en notación interfija a su correspondiente notación postfija y prefija respectivamente. Agregue los métodos siguientes a la clase Expresion iniciada en el Ejercicio 9. Asegúrese de probar sus implementaciones con al menos, los dos ejercicios anteriores:
    1. Postfija (firma del método public String obtenPostfija( )).
    2. Prefija (método public String obtenPrefija( )).
  13. Realice la implementación del Algoritmo de evaluación de una expresión en notación postfija presentado en la entrada Algunas aplicaciones de las pilas. Implemente dicho algoritmo como uno de los servicios de la clase Expresion iniciada en el Ejercicio 9. Proponga una firma de método ad hoc a la responsabilidad de éste pero utilice el identificador evaluaPostfija.
    1. No olvide realizar las pruebas correspondientes para validar y verificar la funcionalidad de su propuesta.
    2. Sugerencia: implemente la realización de la operación representada por símbolo como un método privado; es decir, un método que proporcione servicio a otros métodos de la misma clase (servicio interno), pero no a los objetos instanciados (servicios públicos).
  14. Repita el Ejercicio 9 con la clase Stack del API de Java:
    1. Desde el punto de vista de la ejecución, ¿nota alguna diferencia?
    2. ¿Tendría alguna ventaja o desventaja utilizar el API?
    3. Si la clase Pila del Ejemplo Pila fuera parte del API de Java, ¿cuál utilizaría y por qué?



27 de enero de 2017

A modo de prefacio.

   Estimado lector, este blog tiene una orientación específica. Está pensado como un curso introductorio de programación orientada a objetos en donde, de manera preferente aunque de ninguna manera obligatoria, se haya tenido un contacto previo con algún lenguaje de programación utilizando el enfoque estructurado; sin embargo, también es mi intención que el blog sea de utilidad para aquellos lectores que se quieran iniciar en el mundo de la programación y el paradigma orientado a objetos sin ningún requisito previo de programación.

   El blog asume que el lector posee conocimientos básicos de algoritmos y/o programación, así como el funcionamiento de las estructuras de control secuencial, de selección, y de repetición. Por otro lado, si bien es cierto que para la comprensión del paradigma no son precisos dichos conocimientos (de hecho podrían generar un vicio para un paradigma de programación orientado a objetos más puro), sí lo son para la comprensión y el seguimiento correspondiente de los programas de ejemplo.

   Con todo, el blog proporciona una entrada para apoyar al lector a través de ejemplos selectos tanto en la introducción del lenguaje de programación utilizado, como en los conceptos fundamentales de la programación.

   Existe desde hace mucho tiempo un debate acerca de si es mejor enseñar el paradigma orientado a objetos sin antes tener un conocimiento de otro enfoque de programación (como el estructurado por ejemplo), o si es mejor partir de la programación estructurada para realizar una transición hacia la programación orientada a objetos. En mi opinión ambos enfoques tienen sus ventajas y desventajas.

   Java es un lenguaje de programación híbrido, en el sentido de que no es un lenguaje totalmente orientado a objetos como Smalltalk, y en ese sentido, tiene estructuras de control y tipos de datos primitivos al estilo del lenguaje de programación C, el cual es el lenguaje por antonomasia para la programación estructurada y, dado que este blog utiliza a Java y C++ como lenguajes de programación, aquellos lectores que conozcan el lenguaje C se sentirán familiarizados rápidamente con Java (e indudablemente con C++) concentrándose entonces en la asimilación del paradigma y en su aplicación.

   Por otro lado, aquellos lectores que no conozcan el enfoque estructurado estarían, al menos de primera instancia, sin la predisposición a cometer uno de los vicios más comunes al programar en el enfoque orientado a objetos, como lo es el de utilizar un lenguaje de programación orientado a objetos, para escribir programas en un enfoque estructurado. En éste sentido, resulta fundamental enfatizar desde ahora que el uso de un lenguaje de programación orientado a objetos no hace per se, ni mucho menos garantiza, que los programas que se escriban en dicho lenguaje sigan el modelo de programación orientado a objetos.

   Como en muchas cosas de la vida y lo cotidiano, más que establecer qué es lo mejor y qué no lo es, ya que se está ante una disyuntiva subjetiva, el beneficio dependerá finalmente tanto de las intenciones del lector como de su disposición hacia la comprensión del paradigma orientado a objetos, así como de que se entienda que la asimilación de un nuevo enfoque de programación no es excluyente de otros, sino que la diversidad de enfoques de solución o formas de resolver un problema, amplían el repertorio de conocimientos, herramientas y capacidades en pro de ser progresiva y eventualmente mejores programadores.

   Para ilustrar y complementar de mejor manera tanto el diseño como los conceptos relacionados con los objetos, el blog se apoya de diagramas de clase UML para su correspondiente representación, por lo que sería también de mucha utilidad poseer bases de dicho lenguaje de modelado; sin embargo, tampoco son indispensables.

   La intención del blog es también la de introducir al lector en algunas de las estructuras de datos más convencionales y al mismo tiempo, utilizarlas para ilustrar los conceptos del paradigma orientado a objetos a través de su implementación.

     Finalmente, insisto en que este blog tiene una naturaleza introductoria pero no por ello informal. Confío plenamente en que puede servir como el inicio de un largo camino en la asimilación progresiva de los conceptos asociados con el paradigma orientado a objetos. Espero sinceramente haber podido alcanzar la meta de transmitir los conceptos fundamentales de la orientación a objetos, así como su aplicación en las estructuras de datos utilizando como medios a los lenguajes de programación Java y C++.