Aqui les dejo unas serie de pasos para resolver los problemas mas comunes que se nos puede presentar al usar una computadora..:
APUNTES DE PROGRAMACIÓN ESTRUCTURADA.
MODULO 1: DEFINICION DE CONCEPTOS BASICOS
1.1 ¿QUÉ ES UN LENGUAJE DE PROGRAMACIÓN?
Los lenguajes utilizados para escribir programas de computadoras que puedan ser entendidos por ellos se denominan lenguajes de programación.
Los lenguajes de programación se clasifican en tres categorías:
Lenguajes de Maquina.
Lenguajes de bajo nivel.
Lenguajes de alto nivel.
Lenguaje de Maquina.
Los lenguajes de maquina son aquellos cuyas instrucciones son directamente entendibles por el computador y no necesitan traducción posterior para que la CPU pueda comprender y ejecutar el programa. Las instrucciones en lenguaje de máquina se expresan en términos de la unidad de memoria más pequeña, el bit (dígito binario 0, 1), en esencia una secuencia de bits que especifican la operación y las celdas de memoria implicadas en una operación. Una serie de instrucciones en lenguaje de maquina sería por ejemplo:
0010 0000 0000 1001
1001 0001 1001 1110
Como se puede observar, estas serán fáciles de leer por el computador y difíciles por un programador. Esta razón hace difícil escribir programas en código o lenguaje de máquina y requiere buscar otro lenguaje para comunicarse con el computador, pero que sea más fácil de escribir y leer por el programador.
Para evitar la tediosa tarea de escribir programas en lenguaje de máquina se han diseñado otros lenguajes de programación que facilitan la escritura y posterior ejecución de los programas. Estos lenguajes son los de bajo y alto nivel.
Lenguajes de bajo nivel (ensambladores).
La programación en lenguaje de máquina es difícil, por ello se necesitan lenguajes que permitan simplificar este proceso. Los lenguajes de bajo nivel han sido diseñados para ese fin.
Estos lenguajes son generalmente dependientes de la máquina, es decir, dependen de un conjunto de instrucciones específicas del computador. Un lenguaje típico de bajo nivel es el lenguaje ensamblador. En este lenguaje las instrucciones se escriben en códigos alfabéticos conocidos como nemótecnicos (abreviaturas de palabras inglesas o españolas). Así por ejemplos, nemónicos típicos son:
ADD suma MPY multiplicar LDA cargar acumulador
SUB resta DIV dividir STO almacenar
Las palabras nemotécnicas son mucho más fáciles de recordar que las secuencias de dígitos 0 y 1. Una instrucción típica en ensamblador puede ser:
ADD x, y, z
Después que un programa ha sido escrito en lenguaje ensamblador, se necesita un programa llamado programas ensambladores que lo traduzca a código de máquina.
Lenguajes de alto nivel.
Los lenguajes de alto nivel (Ada, Basic, Cobol, Fortran, Modula-2, Pascal, Visual, Clipper, et.) son aquellos enlos que las instrucciones o sentencias son escritas con palabras similares a los lenguajes humanos (en general lenguaje inglés) lo que facilita la escritura y la fácil comprensión por el programador.
Por ejemplo, la línea siguiente es una línea de un programa en lenguaje QuickBasic:
IF (x=y= AND (z=w) THEN PRINT "Esto es una prueba"
Si (x=y) y (z=w) entonces escribir " Esto es una prueba"
Esta línea se puede comprender fácilmente conociendo la traducción de las palabras inglesas IF (si), THEN (entonces), PRINT (escribir/imprimir), AND (y) y sin necesidad de mucha explicación Se pueden escribir operaciones como:
z := x + y
Los lenguajes de programación son -en general- transportables. Esto significa que un programa escrito en un lenguaje de alto nivel se puede escribir con poca o ninguna modificación en diferentes tipos de computadores. Otra propiedad de estos lenguajes es que son independientes de la máquina, esto es, las sentencias del programa no dependen del diseño hardware de un computador específico (no así el lenguaje ensamblador y de máquina).
Los programas escritos en lenguajes de alto nivel no son entendibles directamente por la máquina., sino que, necesitan ser traducidos a instrucciones en lenguaje máquina que entienda la computadora y para esto existen los programas interpretes y los programas compiladores.
¿Qué es un intérprete y un compilador?
En general los interpretes y compiladores son traductores, este último (compilador) es una máquina teórica que tiene como entada un texto escrito en lenguaje X y como salida un texto escrito en lenguaje Y. Frecuentemente a X se le llama programa fuente y a Y programa objeto.
COMPILADOR
Son programas que realizan la traducción de un lenguaje de programación (alto nivel) a un lenguaje entendible por el computador (código de máquina). Los programas escritos en un lenguaje de alto nivel se llama programas fuentes.
La función del compilador es traducir el programa fuente en uno llamado programa objeto. Este último se utiliza para generar un archivo ejecutable con el programa enlazador. (une distintos programas objetos y genera un programa en lenguaje de maquina o sea ejecutable directamente por la máquina o computador).
En los compiladores, se convierte todo el programa fuente en bloque o código de máquina y después se ejecuta. Así, hay que esperar más que en un interprete para comenzar a ver trabajar el programa, pero después éste funciona mucho más rápido.
INTERPRETE
Son programas similares a los compiladores, y tienen la misma función de traducir los programas de alto nivel. Un intérprete traduce y ejecuta una instrucción del programa (sentencia) paso a paso. Para cada sentencia que compone el texto de entrada (programa), se realiza una traducción, se ejecuta dicha sentencia y se vuelve a iniciar el proceso con la sentencia siguiente. Los programas interpretados generalmente se ejecutan más lentamente que los programas compilados, sin embargo, los intérpretes son mas fáciles de utilizar y la depuración de errores es mucho más cómoda.
En los intérpretes, cada instrucción que contiene el programa se va convirtiendo a código máquina antes de ejecutarla, lo que hace que sean más lentos. Algunos ejemplos de lenguajes interpretados son el BASIC, GW.-BASIC.
La mayoría de los lenguajes de programación de alto nivel actuales son compilables, pudiendo ser interpretados y compilados. Algunas de las cosa que incluyen son:
Un editor de texto para escribir o revisarlos programas.
El compilador que convierta el programa a código de máquina.
Otros módulos auxiliares como enlazadores (linkers) para unir distintos subprogramas, y depuradores (debuggers) para ayudar a descubrir errores.
Algunos ejemplos de lenguajes de programación son:
ADA BASIC COBOL FORTRAN ENSAMBLADOR C PASCAL VISUAL C VISUAL BASIC JAVA SCRIPT FOXPRO CLIPPER COBOLORACLE etc...
A continuación se muestra un esquema para entender mejor el proceso de un compilador. Analizaremos el caso de un programa escrito en lenguaje C que esta conformado por varios módulos (a1, a2, a3...) y al momento de enlazarlo se incorporaran las librerías (módulos prediseñados) necesarias para que el programa funcione .
*.c = archivos o programas fuentes escritos en c.
*.obj = programas objetos.
*.lib = librerías de c.
*.exe = archivo (programa) ejecutable.
Paso 1 : Escribir el programa o programas en un compilador.
Paso 2 : Compilar cada módulo o programa escrito.
Paso 3 : Enlazar los módulos que se quieran unir.
Paso 4 : Ejecutar el programa final.
Esquemáticamente:
a1.c ---- > a1.obj
a2.c ---- > a1.obj
a3.c ---- > a1.obj
a4.c ---- > a1.obj
.
. ---------- > a.exe
..
an.c ---- > a1.obj
lib1.lib
lib2.lib
lib3.lib
APUNTES DE PROGRAMACIÓN ESTRUCTURADA.
MODULO 2: ELEMENTOS DE PROGRAMACION.
2.1 INTRODUCCION.
ANTECECEDENTES
El computador es una herramienta muy poderosa. La información (datos de entrada) puede almacenarse en su memoria y ser manejada a velocidades excepcionalmente altas para producir un resultado (salida del programa). Muchas personas piensan que una computadora puede realizar tareas o trabajos de complejidad superior a una inteligencia humana. La realidad es que una computadora no tiene ninguna inteligencia, no tiene voluntad propia. No puede hacer nada sin que antes se le diga qué tiene que hacer. No olvidemos que no es más que una máquina creada por el hombre y, por tanto, no podrá realizar una tarea que no haya sido previamente determinada por él.
Una Computadora (ordenador) es una máquina de origen electrónico que puede realizar una gran variedad de trabajos, pero, en principio, sólo es capaz de hacer físicamente tres clases de operaciones básicas:
1. Sumar, restar, multiplicar y dividir dos valores numéricos, es decir, realizar operaciones aritméticas sencillas.
2. Comparar dos valores (comprobar si son iguales, si el primero es mayor que el segundo, etc.), es decir, realizar operaciones lógicas sencillas.
3. Almacenar o recuperar información.
Con estas pocas operaciones utilizadas y combinadas de forma adecuada, mediante lo que llamamos programa, se pueden llegar a realizar tareas increíblemente complejas que aporten la solución a un determinado problema, ya sea de gestión, técnico o de cualquier otro tipo. La potencia de cálculo de una computadora se deriva de las características físicas que posee, entre las que se encuentran principalmente: rapidez, precisión y memoria.
Nuestro objetivo es, para un problema dado, diseñar una solución que pueda ser realizada por una computadora. Para ello necesitaremos, en primer lugar, un lenguaje o notación para expresar la solución obtenida. Tal solución debe estar adaptada a las particularidades de la computadora, si bien en una primera fase de su diseño podremos utilizar una notación intermedia entre el lenguaje natural y el de la computadora, posteriormente será preciso escribirla en un lenguaje comprensible por la máquina, como por ejemplo, en COBOL o PASCAL, y, finalmente para su ejecución, la máquina precisará realizar una traducción a su lenguaje nativo, el denominado lenguaje máquina.
INTRODUCCION AL LENGUAJE ENSAMBLADOR
Al desarrollarse las primeras computadoras electrónicas, se vio la necesidad de programarlas, es decir, de almacenar en memoria la información sobre la tarea que iban a ejecutar. Las primeras se usaban como calculadoras simples; se les indicaban los pasos de cálculo, uno por uno. John Von Neumann desarrolló el modelo que lleva su nombre, para describir este concepto de "programa almacenado". En este modelo, se tiene una abstracción de la memoria como un conjunto de celdas, que almacenan simplemente números. Estos números pueden representar dos cosas: los datos, sobre los que va a trabajar el programa; o bien, el programa en sí.
¿Cómo es que describimos un programa como números? Se tenía el problema de representar las acciones que iba a realizar la computadora, y que la memoria, al estar compuesta por switches correspondientes al concepto de bit, solamente nos permitía almacenar números binarios.
La solución que se tomó fue la siguiente: a cada acción que sea capaz de realizar nuestra computadora, asociarle un número, que será su código de operación (opcode) . Por ejemplo, una calculadora programable simple podría asignar los opcodes :
1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE.
Supongamos que queremos realizar la operación 5 * 3 + 2, en la calculadora descrita arriba. En memoria, podríamos "escribir" el programa de la siguiente forma:
Localidad
Opcode Significado Comentario
0 5 5 En esta localidad, tenemos el primer número de la fórmula
1 3 * En esta localidad, tenemos el opcode que representa la multiplicación.
2 3 3 En esta localidad, tenemos el segundo número de la fórmula
3 1 + En esta localidad, tenemos el opcode que representa la suma.
4 2 2 En esta localidad, tenemos el último número de la fórmula
Podemos ver que con esta representación, es simple expresar las operaciones de las que es capaz el hardware (en este caso, nuestra calculadora imaginaria), en la memoria.
La descripción y uso de los opcodes es lo que llamamos lenguaje de máquina. Es decir, la lista de códigos que la máquina va a interpretar como instrucciones, describe las capacidades de programación que tenemos de ella; es el lenguaje más primitivo, depende directamente del hardware, y requiere del programador que conozca el funcionamiento de la máquina al más bajo nivel.
Cuando abstraemos los opcodes y los sustituimos por una palabra que sea una clave de su significado, a la cual comúnmente se le conoce como mnemónico , tenemos el concepto de Lenguaje Ensamblador . Así, podemos definir simplemente al Lenguaje Ensamblador de la siguiente forma: Lenguaje Ensamblador es la primera abstracción del Lenguaje de Máquina, consistente en asociar a los opcodes palabras clave que faciliten su uso por parte del programador
Como se puede ver, el Lenguaje Ensamblador es directamente traducible al Lenguaje de Máquina, y viceversa; simplemente, es una abstracción que facilita su uso para los seres humanos. Por otro lado, la computadora no entiende directamente al Lenguaje Ensamblador; es necesario traducirle a Lenguaje de Máquina. Originalmente, este proceso se hacía a mano, usando para ello hojas donde se escribían tablas de programa similares al ejemplo de la calculadora que vimos arriba Pero, al ser tan directa la traducción, pronto aparecieron los programas Ensambladores, que son traductores que convierten el código fuente (en Lenguaje Ensamblador) a código objeto (es decir, a Lenguaje de Máquina).
Una característica que hay que resaltar, es que al depender estos lenguajes del hardware, hay un distinto Lenguaje de Máquina (y, por consiguiente, un distinto Lenguaje Ensamblador) para cada CPU. Por ejemplo, podemos mencionar tres lenguajes completamente diferentes, que sin embargo vienen de la aplicación de los conceptos anteriores:
1. Lenguaje Ensamblador de la familia Intel 80x86
2. Lenguaje Ensamblador de la familia Motorola 68000
3. Lenguaje Ensamblador del procesador POWER, usado en las IBM RS/6000.
EVOLUCIÓN DE LOS LENGUAJES COMPUTACIONALES
Como se pudo ver en la sección anterior, los lenguajes más primitivos fueron los lenguajes de máquina. Esto, ya que el hardware se desarrolló antes del software, y además cualquier software finalmente tiene que expresarse en el lenguaje que maneja el hardware.
La programación en esos momentos era sumamente tediosa, pues el programador tenía que "bajarse" al nivel de la máquina y decirle, paso a pasito, cada punto de la tarea que tenía que realizar. Además, debía expresarlo en forma numérica; y por supuesto, este proceso era propenso a errores, con lo que la productividad del programador era muy limitada. Sin embargo, hay que recordar que en estos momentos, simplemente aún no existía alternativa.
El primer gran avance que se dio, como ya se comentó, fue la abstracción dada por el Lenguaje Ensamblador, y con él, el nacimiento de las primeras herramientas automáticas para generar el código máquina. Esto redujo los errores triviales, como podía ser el número que correspondía a una operación, que son sumamente engorrosos y difíciles de detectar, pero fáciles de cometer. Sin embargo, aún aquí es fácil para el programador perderse y cometer errores de lógica, pues debe bajar al nivel de la forma en que trabaja el CPU, y entender bien todo lo que sucede dentro de él.
Abstracción.- consiste en descomponer una determinada acción compleja en términos de un número de acciones más simples capaces de ejecutarlas o que constituyan instrucciones de computadora disponibles.
Con el desarrollo en los 50s y 60s de algoritmos de más elevado nivel, y el aumento de poder del hardware, empezaron a entrar al uso de computadoras científicos de otras ramas; ellos conocían mucho de Física, Química y otras ramas similares, pero no de Computación, y por supuesto, les era sumamente complicado trabajar con lenguaje Ensamblador en vez de fórmulas. Así, nació el concepto de Lenguaje de Alto Nivel, con el primer compilador de FORTRAN (FORmula TRANslation), que, como su nombre indica, inició como un "simple" esfuerzo de traducir un lenguaje de fórmulas, al lenguaje ensamblador y por consiguiente al lenguaje de máquina. A partir de FORTRAN, se han desarrollado innumerables lenguajes, que siguen el mismo concepto: buscar la mayor abstracción posible, y facilitar la vida al programador, aumentando la productividad, encargándose los compiladores o intérpretes de traducir el lenguaje de alto nivel, al lenguaje de computadora.
Hay que notar la existencia de lenguajes que combinan características de los de alto nivel y los de bajo nivel (es decir, Ensamblador). Un ejemplo es C: contiene estructuras de programación de alto nivel, y la facilidad de usar librerías que también son características de alto nivel; sin embargo, fue diseñado con muy pocas instrucciones, las cuales son sumamente sencillas, fáciles de traducir al lenguaje de la máquina; y requiere de un entendimiento apropiado de cómo funciona la máquina, el uso de la memoria, etcétera. Por ello, muchas personas consideramos a lenguajes como C (que fue diseñado para hacer sistemas operativos), lenguajes de nivel medio.
VENTAJAS Y DESVENTAJAS DEL LENGUAJE ENSAMBLADOR
Una vez que hemos visto la evolución de los lenguajes, cabe preguntarse: ¿En estos tiempos "modernos", para qué quiero el Lenguaje Ensamblador?
El proceso de evolución trajo consigo algunas desventajas, que ahora veremos como las ventajas de usar el Lenguaje Ensamblador, respecto a un lenguaje de alto nivel:
Velocidad
Eficiencia de tamaño
Flexibilidad
Por otro lado, al ser un lenguaje más primitivo, el Ensamblador tiene ciertas desventajas respecto a los lenguajes de alto nivel:
Tiempo de programación
Programas fuente grandes
Peligro de afectar recursos inesperadamente
Falta de portabilidad
Velocidad
El proceso de traducción que realizan los intérpretes, implica un proceso de cómputo adicional al que el programador quiere realizar. Por ello, nos encontraremos con que un intérprete es siempre más lento que realizar la misma acción en Lenguaje Ensamblador, simplemente porque tiene el costo adicional de estar traduciendo el programa, cada vez que lo ejecutamos.
De ahí nacieron los compiladores, que son mucho más rápidos que los intérpretes, pues hacen la traducción una vez y dejan el código objeto, que ya es Lenguaje de Máquina, y se puede ejecutar muy rápidamente. Aunque el proceso de traducción es más complejo y costoso que el de ensamblar un programa, normalmente podemos despreciarlo, contra las ventajas de codificar el programa más rápidamente.
Sin embargo, la mayor parte de las veces, el código generado por un compilador es menos eficiente que el código equivalente que un programador escribiría. La razón es que el compilador no tiene tanta inteligencia, y requiere ser capaz de crear código genérico, que sirva tanto para un programa como para otro; en cambio, un programador humano puede aprovechar las características específicas del problema, reduciendo la generalidad pero al mismo tiempo, no desperdicia ninguna instrucción, no hace ningún proceso que no sea necesario.
Para darnos una idea, en una PC, y suponiendo que todos son buenos programadores, un programa para ordenar una lista tardará cerca de 20 veces más en Visual Basic (un intérprete), y 2 veces más en C (un compilador), que el equivalente en Ensamblador.
Por ello, cuando es crítica la velocidad del programa, Ensamblador se vuelve un candidato lógico como lenguaje.
Ahora bien, esto no es un absoluto; un programa bien hecho en C puede ser muchas veces más rápido que un programa mal hecho en Ensamblador; sigue siendo sumamente importante la elección apropiada de algoritmos y estructuras de datos. Por ello, se recomienda buscar optimizar primero estos aspectos, en el lenguaje que se desee, y solamente usar Ensamblador cuando se requiere más optimización y no se puede lograr por estos medios.
Tamaño
Por las mismas razones que vimos en el aspecto de velocidad, los compiladores e intérpretes generan más código máquina del necesario; por ello, el programa ejecutable crece. Así, cuando es importante reducir el tamaño del ejecutable, mejorando el uso de la memoria y teniendo también beneficios en velocidad, puede convenir usar el lenguaje Ensamblador. Entre los programas que es crítico el uso mínimo de memoria, tenemos a los virus y manejadores de dispositivos (drivers). Muchos de ellos, por supuesto, están escritos en lenguaje Ensamblador.
Flexibilidad
Las razones anteriores son cuestión de grado: podemos hacer las cosas en otro lenguaje, pero queremos hacerlas más eficientemente. Pero todos los lenguajes de alto nivel tienen limitantes en el control; al hacer abstracciones, limitan su propia capacidad. Es decir, existen tareas que la máquina puede hacer, pero que un lenguaje de alto nivel no permite. Por ejemplo, en Visual Basic no es posible cambiar la resolución del monitor a medio programa; es una limitante, impuesta por la abstracción del GUI Windows. En cambio, en ensamblador es sumamente sencillo, pues tenemos el acceso directo al hardware del monitor.
La flexibilidad consiste en reconocer el hecho de que Todo lo que puede hacerse con una máquina, puede hacerse en el lenguaje ensamblador de esta máquina; los lenguajes de alto nivel tienen en unas u otras formas limitantes para explotar al máximo los recursos de la máquina
Tiempo de programación
Al ser de bajo nivel, el Lenguaje Ensamblador requiere más instrucciones para realizar el mismo proceso, en comparación con un lenguaje de alto nivel. Por otro lado, requiere de más cuidado por parte del programador, pues es propenso a que los errores de lógica se reflejen más fuertemente en la ejecución. Por todo esto, es más lento el desarrollo de programas comparables en Lenguaje Ensamblador que en un lenguaje de alto nivel, pues el programador goza de una menor abstracción.
Programas fuente grandes
Por las mismas razones que aumenta el tiempo, crecen los programas fuentes; simplemente, requerimos más instrucciones primitivas para describir procesos equivalentes. Esto es una desventaja porque dificulta el mantenimiento de los programas, y nuevamente reduce la productividad de los programadores.
Peligro de afectar recursos inesperadamente
Tenemos la ventaja de que todo lo que se puede hacer en la máquina, se puede hacer con el Lenguaje Ensamblador (flexibilidad). El problema es que todo error que podamos cometer, o todo riesgo que podamos tener, podemos tenerlo también en este Lenguaje. Dicho de otra forma, tener mucho poder es útil pero también es peligroso.
En la vida práctica, afortunadamente no ocurre mucho; sin embargo, al programar en este lenguaje verán que es mucho más común que la máquina se "cuelgue", "bloquee" o "se le vaya el avión"; y que se reinicialize. ¿Por qué?, porque con este lenguaje es perfectamente posible (y sencillo) realizar secuencias de instrucciones inválidas, que normalmente no aparecen al usar un lenguaje de alto nivel.
Falta de portabilidad
Como ya se mencionó, existe un lenguaje ensamblador para cada máquina; por ello, evidentemente no es una selección apropiada de lenguaje cuando deseamos codificar en una máquina y luego llevar los programas a otros sistemas operativos o modelos de computadoras. Si bien esto es un problema general a todos los lenguajes, es mucho más notorio en ensamblador: yo puedo reutilizar un 90% o más del código que desarrollo en "C", en una PC, al llevarlo a una RS/6000 con UNIX, y lo mismo si después lo llevo a una Macintosh, siempre y cuando esté bien hecho y siga los estándares de "C", y los principios de la programación estructurada. En cambio, si escribimos el programa en Ensamblador de la PC, por bien que lo desarrollemos y muchos estándares que sigamos, tendremos prácticamente que reescribir el 100 % del código al llevarlo a UNIX, y otra vez lo mismo al llevarlo a Mac.
Los lenguajes con los que comúnmente aprendemos a programar (Pascal, BASIC, Scheme), son llamados de alto nivel, por su mucho mayor grado de abstracción, que permite con pocas instrucciones realizar acciones relativamente complejas para la máquina, que se traducen en muchas instrucciones del lenguaje de máquina o ensamblador.
Existen lenguajes que combinan la abstracción de los lenguajes de alto nivel con el acceso cercano al hardware, como es el caso de C, y se les llama de nivel medio.
DEFINICION DE ALGORITMO Y PROGRAMA.
Algoritmo: Es una serie ordenada, clara y precisa de los pasos que hay que seguir para realizar una tarea o para encontrar la solución del problema planteado.
Un algoritmo debe de reunir las siguientes propiedades:
1. Constar de una secuencia bien definida de pasos.
2. Cada paso debe ser simple y preciso; es decir, constar de una operación elemental claramente definida, por ejemplo: leer un dato, sumar dos números, mandar a cargar un impuesto, etc.
3. Constar de un número finito de pasos para llegar a la solución del problema.
4. Las decisiones deben ser claras.
5. Dar las posibilidades de una solución lo mas general posible; es decir, que permita resolver la mayor variedad de situaciones de una cierta clase, no únicamente un problema en particular.
6. Constar de una secuencia bien definida de pasos.
7. Cada paso debe ser simple y preciso; es decir, constar de una operación elemental claramente definida, por ejemplo: leer un dato, sumar dos números, mandar a cargar un impuesto, etc.
8. Constar de un número finito de pasos para llegar a la solución del problema.
9. Las decisiones deben ser claras.
10. Dar las posibilidades de una solución lo mas general posible; es decir, que permita resolver la mayor variedad de situaciones de una cierta clase, no únicamente un problema en particular.
Programa de computadora.- Es un conjunto de instrucciones - órdenes dadas a la máquina - que producirán la ejecución de una determina tarea. En esencia, un programa es un medio para conseguir un fin. El fin será normalmente definido como la información necesaria para solucionar un problema. Instrucción.- Es un código nemotécnico (enseñanza técnica) que sirve para obtener la ejecución de una actividad en la computadora.
DIFERENCIA ENTRE PROGRAMAR Y CODIFICAR
Programar (Trabajo Conceptual).- Definir acercamientos que resuelvan el problema de manera virtual. Es un proceso mental complejo (imaginar la solución del problema), dividido en varias etapas. La finalidad de la programación, así entendida, es comprender con claridad el problema que va a resolverse o simularse por medio de la computadora y entender con detalle cuál será el procedimiento mediante el cuál la máquina llegará a la solución deseada.
La codificación constituye una etapa necesariamente posterior a la programación, y consiste en describir, en un lenguaje de programación adecuado, la solución ya encontrada o sugerida, por medio de la programación. Es decir, primero se programa la solución de un problema y después se traduce para la computadora
PROGRAMACIÓN ESTRUCTURADA.
MODULO 2: METODOS DE RESOLUCION DE PROBLEMAS
2.1 ¿Cómo resolver problemas?
«Quien quiere hacer algo encuentra un medio; quien no quiere hacer nada encuentra una excusa». (Proverbio chino)
Aunque no es sencillo, y quizás parezca superfluo, para entendernos es interesante delimitar, siquiera sea en grandes rasgos, qué es lo que entendemos por problema. Pero, como la palabra "problema" se usa en contextos diferentes y con matices diversos, haremos un esfuerzo por clarificar a qué nos referimos.
En los ejercicios se puede decidir con rapidez si se saben resolver o no; se trata de aplicar un algoritmo, que pueden conocer o ignorar. Pero, una vez localizado, se aplica y basta. Justamente, la proliferación de ejercicios en clase de matemáticas ha desarrollado y arraigado en los alumnos un síndrome generalizado; en cuanto se les plantea una tarea a realizar, tras una somera reflexión, contestan: "lo sé" o "no lo sé", según hayan localizado o no el algoritmo apropiado. Ahí acaban, en general, sus elucubraciones.
En los problemas no es evidente el camino a seguir; incluso puede haber varios; y desde luego no está codificado y enseñado previamente. Hay que apelar a conocimientos dispersos, y no siempre de matemáticas; hay que relacionar saberes procedentes de campos diferentes, hay que poner a punto relaciones nuevas.
Por tanto, un "problema" sería una cuestión a la que no es posible contestar por aplicación directa de ningún resultado conocido con anterioridad, sino que para resolverla es preciso poner en juego conocimientos diversos, matemáticos o no, y buscar relaciones nuevas entre ellos. Pero además tiene que ser una cuestión que nos interese, que nos provoque las ganas de resolverla, una tarea a la que estemos dispuestos a dedicarle tiempo y esfuerzos. Como consecuencia de todo ello, una vez resuelta nos proporciona una sensación considerable de placer. E incluso, sin haber acabado el proceso, sin haber logrado la solución, también en el proceso de búsqueda, en los avances que vamos realizando, encontraremos una componente placentera.
Aunque los rasgos fundamentales de lo que entendemos por problema están descritos en el párrafo anterior, todavía es conveniente añadir algunos comentarios adicionales sobre los mismos:
• Los algoritmos que se suelen explicar en clase, o que aparecen en los libros de texto, resuelven grupos enteros de problemas. Lo que pasa es que si no situamos previamente los problemas a los que responden, estamos dando la respuesta antes de que exista la pregunta.
• Las situaciones existen en la realidad. Los problemas los alumbramos nosotros. Pasan a ese estatus cuando los asumimos como un reto personal y decidimos en consecuencia dedicarle tiempo y esfuerzos a procurar resolverlos.
• La resolución de un problema añade algo a lo que ya conocíamos; nos proporciona relaciones nuevas entre lo que ya sabíamos o nos aporta otros puntos de vista de situaciones ya conocidas. Suponen el aporte de la chispa de la creatividad, aquella que aparece de cuando en cuando, y que logra, por utilizar la expresión de Koestler (1983), que dos y dos son cinco.
PAUTAS A SEGUIR EN LA RESOLUCIÓN DE PROBLEMAS.
Una vez señaladas las características de los buenos problemas, hay que referirse a la importancia que tiene resolver problemas en clase. Pensemos, que, como dice Polya (1945) «sólo los grandes descubrimientos permiten resolver los grandes problemas, hay, en la solución de todo problema, un poco de descubrimiento»; pero que, si se resuelve un problema y llega a excitar nuestra curiosidad, «este género de experiencia, a una determinada edad, puede determinar el gusto del trabajo intelectual y dejar, tanto en el espíritu como en el carácter, una huella que durará toda una vida».
Para resolver problemas no existen fórmulas mágicas; no hay un conjunto de procedimientos o métodos que aplicándolos lleven necesariamente a la resolución del problema (aún en el caso de que tenga solución). Pero de ahí no hay que sacar en consecuencia una apreciación ampliamente difundida en la sociedad: la única manera de resolver un problema sea por "ideas luminosas", que se tienen o no se tienen.
Es evidente que hay personas que tienen más capacidad para resolver problemas que otras de su misma edad y formación parecida. Que suelen ser las que aplican (generalmente de una manera inconsciente) toda una serie de métodos y mecanismos que suelen resultar especialmente indicados para abordar los problemas. Son los, procesos que se llaman "heurísticos": operaciones mentales que se manifiestan típicamente útiles para resolver problemas.
Es ya clásica, y bien conocida, la formulación que hizo Polya (1945) de las cuatro etapas esenciales para la resolución de un problema, que constituyen el punto de arranque de todos los estudios posteriores:
1. COMPRENDER EL PROBLEMA. Parece, a veces, innecesaria, sobre todo en contextos escolares; pero es de una importancia capital, sobre todo cuando los problemas a resolver no son de formulación estrictamente matemática. Es más, es la tarea más difícil, por ejemplo, cuando se ha de hacer un tratamiento informático: entender cuál es el problema que tenemos que abordar, dados los diferentes lenguajes que hablan el demandante y el informático.
- Se debe leer el enunciado despacio.
- ¿Cuáles son los datos? (lo que conocemos)
- ¿Cuáles son las incógnitas? (lo que buscamos)
- Hay que tratar de encontrar la relación entre los datos y las incógnitas.
- Si se puede, se debe hacer un esquema o dibujo de la situación.
2. TRAZAR UN PLAN PARA RESOLVERLO. Hay que plantearla de una manera flexible y recursiva, alejada del mecanicismo.
- ¿Este problema es parecido a otros que ya conocemos?
- ¿Se puede plantear el problema de otra forma?
- Imaginar un problema parecido pero más sencillo.
- Suponer que el problema ya está resuelto; ¿cómo se relaciona la situación de llegada con la de partida?
- ¿Se utilizan todos los datos cuando se hace el plan?
3. PONER EN PRÁCTICA EL PLAN. También hay que plantearla de una manera flexible y recursiva, alejada del mecanicismo. Y tener en cuenta que el pensamiento no es lineal, que hay saltos continuos entre el diseño del plan y su puesta en práctica.
- Al ejecutar el plan se debe comprobar cada uno de los pasos.
- ¿Se puede ver claramente que cada paso es correcto?
- Antes de hacer algo se debe pensar: ¿qué se consigue con esto?
- Se debe acompañar cada operación matemática de una explicación contando lo que se hace y para qué se hace.
- Cuando se tropieza con alguna dificultad que nos deja bloqueados, se debe volver al principio, reordenar las ideas y probar de nuevo.
4. COMPROBAR LOS RESULTADOS. Es la más importante en la vida diaria, porque supone la confrontación con contexto del resultado obtenido por el modelo del problema que hemos realizado, y su contraste con la realidad que queríamos resolver.
- Leer de nuevo el enunciado y comprobar que lo que se pedía es lo que se ha averiguado. Debemos fijarnos en la solución. ¿Parece lógicamente posible?
- ¿Se puede comprobar la solución? ¿Hay algún otro modo de resolver el problema?
- Se debe acompañar la solución de una explicación que indique claramente lo que se ha hallado.
- Se debe utilizar el resultado obtenido y el proceso seguido para formular y plantear nuevos problemas.
Según S. Fernández las estrategias más frecuentes que se suelen utilizar en la resolución de problemas (1992) serían:
- Ensayo-error.
- Empezar por lo fácil, resolver un problema semejante más sencillo.
- Manipular y experimentar manualmente.
- Descomponer el problema en pequeños problemas (simplificar).
- Experimentar y extraer pautas (inducir).
- Resolver problemas análogos (analogía).
- Seguir un método (organización).
- Hacer esquemas, tablas, dibujos (representación).
- Hacer recuente (conteo).
- Utilizar un método de expresión adecuado: verbal, algebraico, gráfico, numérico (codificar, expresión, comunicación).
- Cambio de estados.
- Sacar partido de la simetría.
- Deducir y sacar conclusiones.
- Conjeturar.
- Principio del palomar.
- Analizar los casos límite.
- Reformular el problema.
- Suponer que no (reducción al absurdo).
- Empezar por el final (dar el problema por resuelto).
A. COMENZAR RESOLVIENDO UN PROBLEMA SEMEJANTE MÁS FÁCIL.
La simplificación de un problema se puede lograr no sólo reduciendo su tamaño, sino también imponiendo alguna condición adicional que no está en el problema propuesto. Incluso, aunque parezca al principio que tu simplificación es demasiado drástica, se comprueba con frecuencia cómo la ayuda del problema simplificado es muy efectiva.
UNA MOSCA ANTOJADIZA. Colocamos sobre la mesa 25 monedas iguales en la siguiente posición:
O O O O O
O O O O O
O O O O O
O O O O O
O O O O O
Una mosca viene volando y se posa sobre una de ellas (la indicada). Se le ocurre hacer un paseo andando por las 25 monedas, pero, pasando de una moneda a otra horizontalmente y verticalmente y sin repetir moneda. ¿Lo podrá hacer? ¿Qué itinerario sería el adecuado para cada moneda en la que se pueda posar?
Solución. Son muchas 25 monedas. Vamos a probar con menos, por ejemplo, con 2x2=4 monedas. Así:
O O
O O
Es obvio que se pose donde se pose, la mosca tiene el camino bien fácil.
Probemos con 3x3=9 monedas. Así:
O O O
O O O
O O O
Si la mosca se posa en una esquina también lo tiene fácil. Si se posa en el centro, también. Pero si se posa en cualquier otra moneda, como fácilmente se observa, lo tiene imposible.
Así, en el caso de 3x3=9 monedas, a veces se puede hacer el paseo, y otras no. Podemos sospechar que en el de 5x5=25 monedas suceda algo parecido.
¿Por qué no se puede hacer el paseo en algunos casos cuando hay 9 monedas?
Señalemos los centros de las monedas con coordenadas:
(-1,1) (0,1) (1,1)
(-1,0) (0,0) (1,0)
(-1,-1) (0,-1) (1,-1)
Es curioso: ¡los puntos desde los que el paseo no se puede hacer son (0,1), (1,0), (0,-1), (-1,0)! En ellos, la suma de las coordenadas es impar. En los restantes, la suma de las coordenadas es par. Llamaremos pares a estos vértices y, a los otros, impares.
Hay cuatro vértices impares y cinco pares. El paseo de la mosca, empezando por un vértice impar, sería:
Impar Par Impar Par ...
Si terminase en impar, habría más vértices impares que pares. Si terminase en par, habría igual número de las dos clases. Ambas cosas son falsas. ¡La mosca no puede hacer el paseo saliendo de un vértice impar!
Esto da luz más que suficiente para tratar el caso de 5x5 monedas. El camino en los casos en los que se puede hacer se encuentra fácilmente.