sábado, 20 de noviembre de 2010

Programación Orientada a Objetos. Una nueva forma de pensar.

En esta ocasión conoceremos un nuevo esquema de programación totalmente distinto a lo que conocimos anteriormente, hablamos de la programación orientada a objetos.

Pero ¿que es la Programación Orientada a Objetos?

En este nuevo modelo, cambia totalmente a lo que comúnmente estábamos acostumbrados en la programación imperativa. Por mencionar un ejemplo, algunos lenguajes no orientados a objetos como Pascal, Basic, C entre otros basan su funcionamiento en el concepto de función. La función lo podremos definir como un conjunto de instrucciones que efectúan un resultado,  de este modo los programas desarrollados en dicho paradigma no son mas una serie de llamadas entre el programa principal y el sistema operativo.

En la programación orientada a objetos cambia este esquema, ya que el elemento principal no es una función en si,  si no lo que se conoce como un objeto.

Un objeto es la representación en un programa de un concepto, y este contiene toda la
información necesaria para abstraerlo: datos que describen sus atributos y operaciones
que pueden realizarse sobre los mismos.

De esta forma la Programación Orientada a Objetos es una nueva forma de pensar una manera distinta de resolver los problemas.

Siempre se entienden mejor las cosas cuando nosotros aplicamos un ejemplo a las nuevas cosas que estamos aprendiendo, de este modo el siguiente ejemplo mostrara la forma de pensar de dicho paradigma de programación.

Si nos detenemos un momento a analizar como resolver determinado problema de programacion, al analizar con detalle los elementos o la manera en que lo podemos resolver,  descubrimos que los elementos de ese problema, si lo vemos de una forma algo abstracta podemos ver que forman una “entidad” (o también podríamos llamarlo un individuo u objeto). Estas entidades poseen un conjunto de propiedades o atributos, y un conjunto de métodos mediante los cuales muestran su comportamiento.

Y no sólo eso, también podremos descubrir,  un conjunto de interrelaciones entre las entidades, guiadas por el intercambio de mensajes; las entidades del problema responden a estos mensajes mediante la ejecución de ciertas acciones.

El siguiente ejemplo es algo raro pero sirve muy bien para que se comprendan algunos conceptos de la filosofía de la programación orientada a objetos.

Imaginemos el siguiente escenario:

Es un día viernes como cualquier otro, y yo me encuentro en casa junto a mi hermanita pequeña, de repente a mi hermanita tiene demasiada hambre; como seria mi reacción natural me dirigiría a la cocina a buscar algo de comer.

La situación anterior puede resultar un tanto extraña, pero ahora si la analizamos en términos de objetos podremos descubrir lo siguiente: El objeto “Hermano” ha  recibido un mensaje procedente del objeto “Hermanita”. El objeto ”hermano” responde al mensaje mediante una acción: buscar comida. El objeto “hermanita” no tiene que decirle al objeto “hermano” como resolver el problema, es responsabilidad del objeto “hermano” resolver el problema como considere mas conveniente.Continuemos con el escenario:

El hermano al dirigirse al refrigerador descubre que no hay nada para comer ya que es viernes. Entonces el hermano acude a una cadena de comida rápida, donde es atendido por una señorita la cual pregunta “¿que desea llevar?” a lo que el hermano responde:” una orden de pollo”. Entonces la señorita del restaurante desaparece y al poco tiempo regresa con una orden de pollo en las manos. El hermano paga el importe del producto y se regresa a su casa. En casa  el hermano le proporciona el alimento a su hermanita que luego de un rato comienza a sentirse mejor .

El objeto hermano, sabe que es lo tiene que hacer para resolver el problema, en este caso conseguir alimento. Para esto entra en juego un nuevo objeto, el objeto “señorita” quien responde al mensaje del objeto “hermano” consiguiendo el alimento. Ahora el objeto “señorita” es responsable de la solución del problema. Después el objeto “señorita” emite un mensaje al objeto “hermano” pidiéndole pagar el importe, el objeto “hermano” responde a tal mensaje con la acción de pagar.

Como hemos podido ver, en la historia nos encontramos con varios objetos que se diferencian de los demás por un conjunto de características y propiedades, también por un conjunto de acciones que realizaban en respuesta a unos eventos que se originaban en otros objetos o en el entorno.

También podemos darnos cuenta de que, aunque todos los objetos tienen propiedades
distintas, como el color del cabello, altura, edad, todos tienen un conjunto de atributos en común por ser ejemplos son de una misma entidad llamada “ser humano”. A este conjunto de objetos (en nuestro caso “ser humano”) lo llamaremos clase.

Con el ejemplo anterior espero que se comprenda que los objetos son casos particulares de las clases, y  que las clases no son mas que una ”plantilla” que definen los comportamientos, variables, y métodos comunes a todos los objetos de un mismo tipo.

En este caso vemos que la clase “ser humano” tiene entre sus muchas variables que la componen: el color de ojos, color de piel, estatura, peso, etcétera. Ahora lo importante es mencionar que a partir de una determinada clase, se pueden definir todos los objetos que se quieran especificando valores particulares para cada objeto, definidos anteriormente en las clases. Así  encontrarnos en el objeto “señorita” cuyo color de cabello es castaño, ojos negros, con una estatura 170 cm,  y así atributos específicos para cada objeto derivado esa clase.

Ahora veremos con mas detalle lo que son los objetos y las clases, las formas en que se comunican y varias definiciones de la programacion orientada a objetos.

Un objeto no es más que un conjunto de variables (datos) y métodos (funciones)
relacionados entre sí. Los objetos en programación se usan para modelar objetos o
entidades del mundo real (en el ejemplo anterior el objeto hermano, hermanita, o señorita). Un objeto es, por tanto, la representación en un programa de un concepto, y contiene toda la información necesaria para abstraerlo: datos que describen sus atributos y operaciones que pueden realizarse sobre los mismos.

OBJETO

 

Los atributos del objeto (estado) y lo que el objeto puede hacer (comportamiento) están
expresados por las variables y los métodos que componen el objeto respectivamente.
Por ejemplo, un objeto que modelase un auto en el mundo real tendría variables
que indicarían el estado actual de la bicicleta: su velocidad es de 20 km/h, su cadencia
de pedaleo 90 r.p.m. y su marcha actual es la 5ª. Estas variables se conocen
formalmente como variables instancia o variables miembro porque contienen el estado
de un objeto bicicleta particular y, en programación orientada a objetos, un objeto
particular se denomina una instancia.

Además de estas variables, el objeto bicicleta podría tener métodos para frenar, cambiar
la cadencia de pedaleo, y cambiar de marcha (la bicicleta no tendría que tener un
método para cambiar su velocidad pues ésta es función de la cadencia de pedaleo, la
marcha en la que está y de si los frenos están siendo utilizados o no, entre otros muchos
factores). Estos métodos se denominan formalmente métodos instancia o métodos
miembro, ya que cambian el estado de una instancia u objeto bicicleta particular.

El siguiente esquema lo muestra de una manera mas clara.

BICI COMO OBJETO

El diagrama del objeto bicicleta muestra las variables objeto en el núcleo o centro del
objeto y los métodos rodeando el núcleo y protegiéndolo de otros objetos del programa.
Este hecho de empaquetar o proteger las variables miembro con los métodos miembro
se denomina encapsulación. Este dibujo que muestra el núcleo de variables
miembro del objeto protegido por una membrana protectora de métodos o funciones
miembro es la representación ideal de un objeto y es el ideal que los programadores de
Bicicleta modelada como objetos suelen buscar. Sin embargo a menudo, por razones prácticas, es posible que un objeto desee exponer alguna de sus variables miembro, o proteger otras de sus propios métodos o funciones miembro. Por ejemplo, Java permite establecer 4 niveles de protección de las variables y de las funciones miembro para casos como éste. Los niveles de protección determinan qué objetos y clases pueden acceder a qué variables o a qué métodos.

El hecho de encapsular las variables y las funciones miembro
relacionadas proporciona dos importantes beneficios a los programadores de
aplicaciones:

Capacidad de crear módulos: El código fuente de un objeto puede escribirse y
mantenerse independiente del código fuente del resto de los objetos. De esta
forma, un objeto puede pasarse fácilmente de una parte a otra del programa.
Podemos dejar nuestra bicicleta a un amigo, y ésta seguirá funcionando.
Protección de información: Un objeto tendrá una interfaz pública
perfectamente definida que otros objetos podrán usar para comunicarse con él.
De esta forma, los objetos pueden mantener información privada y pueden
cambiar el modo de operar de sus funciones miembros sin que esto afecte a otros
objetos que usen estas funciones miembro. Es decir, no necesitamos entender
cómo funciona el mecanismo de cambio de marcha para hacer uso de él.

Los mensajes.

Un único objeto por sí solo no es muy útil. En general, un objeto aparece
como un componente más de un programa o una aplicación que contiene otros muchos
objetos. Es precisamente haciendo uso de esta interacción como los programadores
consiguen una funcionalidad de mayor orden y modelar comportamientos mucho más
complejos. Una bicicleta (como objeto) guardada en tu casa por sí sola, la bicicleta es incapaz de desarrollar alguna actividad. Tu bicicleta es realmente útil en tanto que otro objeto (tú) interactúa con ella (pedalea).

Los objetos de un programa interactúan y se comunican entre ellos por medio de
mensajes. Cuando un objeto A quiere que otro objeto B ejecute una de sus funciones
miembro (métodos de B), el objeto A manda un mensaje al objeto B.

¿Que es una clase?

en el mundo real existen varios objetos de un mismo tipo, o como
diremos, de una misma clase. Por ejemplo, mi bicicleta es una de las muchas
bicicletas que existen en el mundo. Usando la terminología de la programación
orientada a objetos, diremos que mi bicicleta es una instancia de la clase de objetos
conocida como bicicletas. Todas las bicicletas tienen algunos estados o atributos (color,
marcha actual, cadencia actual, dos ruedas) y algunos métodos (cambiar de marcha,
frenar) en común. Sin embargo, el estado particular de cada bicicleta es independiente
del estado de las demás bicicletas. La particularización de estos atributos puede ser
diferente. Es decir, una bicicleta podrá ser azul, y otra roja, pero ambas tienen en común
el hecho de tener una variable “color”. De este modo podemos definir una plantilla de
variables y métodos para todas las bicicletas. Las plantillas para crear objetos son
denominadas clases.
Una clase es una plantilla que define las variables y los métodos que son comunes para
todos los objetos de un cierto tipo.

La herencia.

Ya que conocemos el concepto de clase y el de objeto, estamos preparados de
introducir otra de las características básicas de la programación orientada a objetos: el
uso de la herencia.
La herencia permite definir nuevas clases partiendo de otras ya
existentes. Las clases que derivan de otras heredan automáticamente todo su
comportamiento, pero además pueden introducir características particulares propias que
las diferencian.

La programación orientada a objetos va más allá, permitiéndonos definir clases a partir
de otras clases ya construidas. Por ejemplo, las bicicletas de montaña, las de carretera y los triciclos son todos, en definitiva, bicicletas. En términos de programación orientada
a objetos, son subclases o clases derivadas de la clase bicicleta. Análogamente, la clase
bicicleta es la clase base o superclase de las bicicletas de montaña, las de carretera y los triciclos.

Una importante característica es que estas subclases no se limitan a los estados y los comportamientos que heredan de su clase base. Muy al contrario, estas subclases
pueden añadir variables y métodos a aquellas que han heredado.Las clases derivadas pueden incluso sobrescribir los métodos heredados y proporcionar implementaciones más especializadas para esos métodos.

La herencia es una herramienta clave para abordar la resolución de un problema de
forma organizada, pues permite definir una relación en una forma jerárquica entre todos los conceptos que se están manejando. Es posible emplear esta técnica para descomponer un problema de cierta magnitud en un conjunto de problemas subordinados a él.

Referencias:

Introducción a la programacion orientada a objetos.-Luis R. Izquierdo-

Programacion Orientada a Objetos con Java, una introducción practica usando BlueJ.-David J. Barnes –Michael K. Editorial PEARSON 3a Edición.

http://es.wikipedia.org/wiki/Herencia_(inform%C3%A1tica)

http://es.wikipedia.org/wiki/Objeto_(programaci%C3%B3n)

http://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos

http://es.wikipedia.org/wiki/Clase_(inform%C3%A1tica)

miércoles, 17 de noviembre de 2010

Patrones de diseño.

Mucha de la información que uno encuentra en internet, que explica sobre lo que son los patrones de diseño, no lo explican de manera clara a las personas que nunca antes escucharon el termino,ya que utilizan definiciones bastante formales es por ello que cuando comenzamos a estudiar dichos términos pueden tornarse algo confusos o incluso tomar otro significado.

La siguiente entrada tratare de explicar lo que es un patrón de diseño para que personas que nunca antes hallan escuchado dicho termino no se les torne tan complicada la definición.

Cuando queremos resolver determinado problema de programación, al momento que estamos programando su solución es común que ciertas instrucciones las escribamos sin pensarlo mucho ya que con la misma practica vamos construyendo nuestro programa.

Ahora imaginemos que después surge otro problema similar al anterior, solo que un poco mas complejo. En este caso caemos en la necesidad de reutilizar el código que anteriormente utilizamos en el programa y agregar los detalles que este nuevo programa lo requiera, esto para ahorrarnos un poco de trabajo y tiempo.

Con el tiempo esto se torna un tanto rutinario y los programadores, tratan de averiguar nuevas formas para que el proceso de utilizar el código sea mucho mas cómodo  y que este sea lo suficientemente versátil como para no volver a modificarlo.

Entonces los programadores se dieron cuenta de este problema de tener que reescribir todas las líneas de código una y otra vez,si así su programa lo requiriera. Es por ello que así surgen lo que hoy conocemos como patrones de diseño, una forma en que todos esos códigos utilizados anteriormente pueden volver a ser reutilizados.

Los patrones de diseño nos ayudan a que nuestro código pueda volver a ser reutilizable en el momento que así lo requiriéramos, y así realizar las tareas mucho mas complejas que nos se nos presenten y esto sin necesidad de tocar el código anterior.

Dado lo anterior podemos afirmar entonces que un patrón de programación es un conjunto de soluciones a problemas que generalmente encuentras en el diseño de un programa. Cada patrón explica cómo resolver un determinado problema, bajo determinadas circunstancias, y las ventajas y desventajas de su uso.

Dependiendo de la naturaleza del problema a resolver, será el patrón mas conveniente a utilizar, en este caso nos podemos encontrar con patrones de creación, estructurales y de comportamiento.

 

  • Patrones de creación. Estos patrones se utilizan cuando debemos crear objetos pero debemos tomar decisiones dinámicamente en el proceso de creación. Para esto lo que hacemos es abstraer el proceso de creación de los objetos para realizar la decisión de qué objetos crear o cómo crearlos para el momento en que se tenga que hacer. Patrones de creación son: Abstract Factory, Builder, Factory Method, Object Pool, Prototype y Singleton.
  • Patrones estructurales. Nos describen como utilizar estructuras de datos complejas a partir de elementos más simples. Sirven para crear las interconexiones entre los distintos objetos y que estas relaciones no se vean afectadas por cambios en los requisitos del programa. Algunos ejemplos de patrones estructurales son: Adapter, Bridge, Decorator, Facade, Flyweight y Proxy.
  • Patrones de comportamiento. Fundamentalmente especifican el comportamiento entre objetos de nuestro programa. Hay varios: Chain of Responsability, Command, Interpreter, Iterator, Mediator, Memento (o Snapshot), Observer, State, Strategy, Template Method y Visitor.

 

No hay que preocuparse en este momento si todas estas definiciones tal vez suelen tornarse un poco confusas ya que aun no nos adentramos de lleno en el tema, pero ya en Programación Orientada a Objetos se vera con mucha mas detalle todas estas definiciones.

Si le interesa aprender patrones de diseño, pueden consultar el libro: UML y PATRONES, Introducción al análisis y diseño orientado a objetos el autor es Craig Larman y su editorial es PEARSON. Hay una versión en español por si les interesa ;)

Referencias recomendadas:

http://hanzcocchi.net/libro-uml-y-patrones-de-disenio/

http://msdn.microsoft.com/es-es/library/bb972240.aspx

http://www.davidvalverde.com/blog/tipos-de-patrones-de-diseno/

http://blog.innocuo.com/archive/2006/09/11/patrones-de-diseno-la-importancia-de-aprenderlos/

http://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o

http://catarina.udlap.mx/u_dl_a/tales/documentos/lis/diaz_c_a/capitulo4.pdf

martes, 16 de noviembre de 2010

Problema de los puentes de Königsberg. Los orígenes de la Teoría de Grafos.

Es un interesante problema que debería de explicarse cuando apenas nos adentramos al estudio de la teoría de grafos, ya que en si este problema refleja la importancia de dicho campo, como se van modelando problemas del mundo real como graficas y a su vez conocer el concepto de un ciclo Euleriano. Este problema da inicio a la teoría de grafos.
El problema dice lo siguiente:
Dado el mapa de Königsberg, con el río Pregolya dividiendo el plano en cuatro regiones distintas, que están unidas a través de los siete puentes, ¿es posible dar un paseo comenzando desde cualquiera de estas regiones, de modo de recorrerlas todas pasando sólo una vez por cada puente, y regresando al mismo punto de origen?

untitled
 
Imaginemos si lo intentáramos resolver mediante fuerza bruta, intentando cada una de las posibilidades hasta el cansancio, obviamente sin llegar al resultado esperado :P
Leonhard Euler un matemático en el año 1736 propone una ingeniosa y a la vez sencilla, forma de solucionar el problema, no solo para este caso, si no para muchos más que pueden diferir en la cantidad de puentes.
Euler formuló el problema de la siguiente manera: “En la ciudad de Königsberg, en Prusia, hay una isla llamada Kneiphof, rodeada por los dos brazos del río Pregel. Hay siete puentes a, b, c, d, e, f y g, que cruzan por los dos brazos del río. La cuestión consiste en determinar si una persona puede realizar un paseo de tal forma que cruce cada uno de estos puentes sólo una vez”.
01


Euler primeramente realizo una abstracción del modelo del mapa, quedando de una manera mucho más simple en donde él representa con puntos las regiones y con líneas los puentes que hay entre punto a punto. De esta forma el problema se reduce considerablemente.
 
Dibujo
Como resultado de ello Euler llego a la conclusión que no existe un camino, en el que pueda recorrer toda la ciudad solo pasando una sola vez.
Pero como sabemos los matemáticos son bastante analíticos, Euler no se conformo con dejarlo así, si no que nos dio una explicación razonable.
Según Euler, todo se basaba en utilizar una notación adecuada.


Entonces , Euler llamó A, B, C y D a las distintas regiones de Königsberg. El camino que va desde A hasta B puede ser por el puente a o por el b, pero Euler lo designó por AB. Una vez allí, para ir a D, se sigue el camino BD, designando la trayectoria total por ABD, y así sucesivamente hasta recorrer todas las zonas y puentes, de manera que al final se obtendrá una combinación de ocho letras. Sin embargo esta notación tiene un inconveniente, y es que no tiene en cuenta que para ir de una zona a otra puede que exista más de un puente.

En dicha combinación de letras, el camino AB debería aparecer dos veces, ya que también está el BA; el camino CA habría de aparecer otras dos veces; y tan sólo una los caminos AD, BD, y CD. Por lo tanto, las letras A, B, C, D, deben formar una serie de ocho letras, apareciendo el número requerido de veces las combinaciones de las mismas.
 

Euler vio que esta situación concreta no era posible, ya que, por ejemplo, si se empieza en la región A, si esta región sólo conectara con el puente a, como puede que se llegue o se venga de ella, la letra A aparecería una vez en la combinación de 8 letras. Si hubiera tres puentes que condujeran a la zona, entonces la letra A aparecería dos veces. Pero como llegan cinco puentes, en este caso, A debe aparecer tres veces en esa sucesión. Similarmente, B estaría dos veces; al igual que D y C. Pero entonces, ya tendríamos nueve letras en la sucesión, cuando para ser la ruta posible únicamente deberían haber ocho. Euler dedujo entonces que no se podía realizar la travesía requerida a través de los siete puentes de Königsberg .

Sin embargo, y como comente anteriormente, Euler no se contentó sólo con solucionar esta situación concreta, sino que se dedicó por completo al estudio del problema en general, obteniendo una solución que servía también para cualquier número de puentes.
Para ello, el procedimiento que siguió Euler consistió en lo siguiente: en primer lugar, apuntó en un papel el número de puentes más uno (ocho, en el caso de Königsberg ). Después, abajo a la izquierda formó una columna con todas las letras de las regiones (A, B, C y D, en este caso). A su derecha, formó una segunda columna con el número de puentes que salen de cada una de las correspondientes zonas (5, 3, 3 y 3, en este caso), marcando con un asterisco aquellas letras de las que salen un número par de puentes.

Después realizó las siguientes operaciones con los números de la segunda columna: si el número de la segunda columna (número de puentes que llegan a una determinada región) es impar, lo sumo en una unidad y lo dividió entre dos. Si el número es par, lo dividió entre dos. Euler colocó finalmente a la derecha una tercera columna con las cuentas anteriormente especificadas (3, 2,2, 2, en nuestro caso).

003
Euler  entonces llego a la conclusión que el problema sólo tendría solución si la suma de los números de la última columna es menor o igual al numero de puentes sumando una unidad. En este caso 7 puentes sumando 1 dando lugar a 8. Ese debería de ser la sumatoria de la ultima columna en dado caso que existiera una solución. En nuestro caso la sumatoria es igual a 9 es por ello que Euler determino que no existe una solución para el problema de los puentes de Königsberg
Para comprender mucho mejor la manera en que Euler resolvio el problema, es importante apreciar las siguientes cuestiones:
•La suma de los números de la segunda columna, es siempre par, ya que su          mitad refleja el número de puentes.
• Si la suma de dichos números se aumenta en dos unidades y luego se divide entre dos, el resultado es el número escrito en la parte superior de la tabla construida.
• Si los números de la segunda columna son todos pares, la tercera columna, formada por las mitades de ellos, sumará una unidad menor que el número escrito inicialmente de la tabla (con lo que la ruta será siempre posible)
• Si en la segunda columna hay sólo dos números impares, la ruta requerida será también siempre posible, porque la suma de la tercera columna coincidirá con el número inicial.
• Si hay más de dos números impares en la segunda columna,la ruta no será nunca posible, pues la suma de la tercera columna superará siempre al número inicialmente escrito.
Entonces Euler dedujo algunas  reglas para cruzar todos los puentes una sola
vez, se tienen que cumplir las siguientes condiciones:
• Si hay más de dos regiones a las que conducen un número impar de puentes, la ruta no será posible.
• Si sólo hay dos regiones a las que llega un número impar de puentes, la ruta se podrá realizar, comenzando en una de esas regiones.
• Si no hay regiones a las que conduzcan un número impar de puentes, la ruta pedida se podrá realizar, comenzando en cualquier punto.
Con esto Euler dio inicio a las primeras nociones de un grafo, donde el modeló el problema de los 7 puentes como un grafo, los vértices representaban cada una de las regiones y las aristas las conexiones entre ellas.
Con la demostración de Euler, también surgió lo que conocemos en teoría de graficas como ciclo euleriano, llamado así justamente en honor a Leonhard Euler, que representa cualquier camino dentro de un grafo particular, capaz de recorrer todas las aristas una única vez, regresando finalmente al mismo vértice original.

Referencias recomendadas:
http://en.wikipedia.org/wiki/Seven_Bridges_of_K%C3%B6nigsberg
http://mathforum.org/isaac/problems/bridges1.html
http://en.wikipedia.org/wiki/Eulerian_path
http://www.iesezequielgonzalez.com/matematicas/grafos.htm
http://es.wikipedia.org/wiki/Problema_de_los_puentes_de_K%C3%B6nigsberg
http://es.wikipedia.org/wiki/Ciclo_euleriano

Script gracioso en Java Script.

Hace un rato que estaba revisando mi correo, me encontré con algo interesante, un coreo del año 2006, en donde me envían un script (escrito en java script) mostrándome un montón de ventanas con mensajes graciosos y hasta que no finalizara la ejecución del script era cuando las ventanitas se detenían.

Sinceramente me es imposible citar alguna referencia con dicho script ya que fue hace bastante tiempo y aparte que el mismo se encuentra alojado en mi correo, por ello me es difícil saber cual es la fuente original del mismo.

En particular cuando lo analizaba no era la gran cosa, sin embargo hay algunas cosas que modifique de dicho script como algunos mensajes (ya que había algunos muy fuera de lugar y que eran un poco inapropiados :P)

El script lo subí a un servidor de Windows Live Messenger.

Advertencia:  El script es un poco molesto :P queda a criterio del usuario la ejecución del mismo :P

El link es el siguiente:

http://cid-0e91a056bbe131c6.office.live.com/self.aspx/P%c3%bablico/script%20molesto.html

El funcionamiento del script es bien sencillo, básicamente la mayoría de las instrucciones son los comandos que envían un mensaje al usuario, en este caso la instrucción

<SCRIPT>alert ('Aquí escribes tu mensaje')</SCRIPT>

La otra instrucción interesante es:

var namePrompt=prompt("Cual es su nombre","");
function dispname(namePrompt) {
document.write(""+namePrompt+"");

}
{dispname(namePrompt);
}

Que básicamente lo que hace es preguntar el nombre del usuario, lo guarda para posteriormente imprimirlo al usuario.

La ultima instrucción pero no de gran importancia es la siguiente:

<FONT face="Comic Sans MS" color=00FF00 size=10>

Que básicamente elegimos el tipo de fuente a utilizar, en este caso Comic Sans MS, el color en este caso de la paleta de colores RGB en HTML en este caso el color utilizado 00FF00 corresponde al color verde y con size se define el tamaño de la fuente.

Y con estos tres elementos principales se compone el script anterior, no es tan complicado ¿verdad?

En caso de que quieran revisar el código fuente del mismo, bastaría con abrir el archivo con cualquier editor de textos =)

domingo, 7 de noviembre de 2010

Lenguajes Logicos.


En clase se estudiaron ya varios tipos de lenguajes, que entran en la categoría de paradigma imperativo y paradigma funcional, en esta ocasión estudiaremos el paradigma lógico.
Sabemos que las aplicaciones que hemos desarrollado casi siempre siguen un mismo esquema, por ejemplo casi siempre nuestros programas involucran operaciones aritméticas, secuencias de instrucciones, etc. Muchas veces es difícil (inclusive para un programador experimentado) tratar de modelar cierto problema con la programación tradicional.
Hoy en día estos lenguajes que pertenecen a la categoría del paradigma imperativo, han evolucionado bastante que ya no es tan complicado como en varios años.
Para poder resolver problemas de este tipo tenemos a la programación lógica, que es una manera más sencilla, para el intelecto humano, de expresar problemas complejos y así poder resolverlos mediante la aplicación de reglas, hipótesis y teoremas.
De ahí surgen los lenguajes del paradigma lógico, en donde es más factible resolver ciertos problemas en donde la programación tradicional sería un fracaso.
Para tratar de demostrar esto, nuestra tarea consiste en elegir un problema lógico y modelar su solución, aplicando varias reglas de lógica, algunos teoremas del álgebra booleana, etc..
El problema que elegí está un poco largo pero no es nada del otro mundo que no podamos comprender ya que aplicaremos conceptos ya vistos en matemáticas discretas y en sistemas digitales. Está un poco encaminado al área de la electrónica digital pero sigue los mismos principios de la lógica computacional.
Mi problema es el siguiente:
Granja de Ovejas
Un granjero requiere de una alarma para detectar cuando hay peligro para sus ovejas ya que cercas del rancho, hay una manada de lobos y pueden ser devorados por ellos. El rancho cuenta con una puerta grande que solo puede ser cerrada o abierta por varios trabajadores.
Entonces hay que diseñar un sistema que
1-active la alarma cuando las ovejas estén fuera del corral y la puerta este abierta
2-active la alarma cuando los lobos estén cercas y las ovejas fuera del corral.
Todo esto aplicando reglas de lógica, y algunos teoremas.
Para ello tomaremos como variables de entrada: las ovejas, los lobos y la puerta.
La salida resultante sería la función de la alarma que implementaremos.
Entonces lo siguiente que realizaremos será una tabla de verdad en donde veremos todas las posibles condiciones.
Tomaremos los siguientes valores para trabajar.
Si la puerta está cerrada tomaremos como un 0
Si la puerta está abierta tomaremos como un 1

Si las ovejas están fuera del corral tomaremos como un 1
Si las ovejas están dentro del corral tomaremos como un 0

Si los lobos están cerca tomaremos como un 1
Si los lobos están lejos tomaremos como un 0 



Este comportamiento lo vemos representado en la tabla de verdad con todas las condiciones posibles, cuando se activara la alarma. 


Para que se comprenda mucho mejor los conceptos y tener un mejor control sobre las variables, utilizaremos las variables A para representar las ovejas, B para representar la puerta y C para representar los lobos.
Luego de esto obtendremos la función que representa el comportamiento anterior que estaría dada por la siguiente:
F=A¬ B C+A B C¬+A B C
donde solo tomaremos los resultados verdaderos para construir dicha función. Para aclaración el símbolo “¬” indica que el termino es negado.
Posteriormente de la tabla de verdad obtenida, haremos uso de algunos teoremas para reducir esta expresión algebraica booleana, estos teoremas son ampliamente utilizados en el diseño secuencial.

Haremos uso del mapa de Karnaugh. ¿Pero que son entonces los mapas de karnaugh?
Los Mapas de Karnaugh son una herramienta muy utilizada para la simplificación de circuitos lógicos. Cuando se tiene una función lógica con su tabla de verdad y se desea implementar esa función de la manera más económica posible se utiliza este método.
Para armar nuestro mapa se utiliza la formula 2^ n donde n es el numero de variables que utilizamos, en nuestro caso 3 variables, sustituyendo quedaría 2^3 que sería igual a 8. Ese será el número de casillas de nuestro mapa de Karnaugh.
Luego vamos llenando nuestro mapa con los resultados de la tabla de verdad, asignándolos en la posición correspondiente de acuerdo con nuestro mapa, por ejemplo en nuestra tabla de verdad en la posición 001 tenemos una salida que es igual a 0, posteriormente buscamos esa posición en nuestro mapa de Karnaugh y el resultado lo representaremos ahí. Haremos lo mismo con todos los valores de la tabla de verdad hasta llenar nuestro mapa de Karnaugh. 











Para que se comprenda mejor el llenado de la tabla, haremos las siguientes aclaraciones: Las dos primeras filas indican los valores que puede tomar la variable “Lobos” o la variable “C” en este caso primera fila donde C = 0 y segunda fila donde C = 1; La primera columna donde se puede observar los dos ceros agrupados, esta columna representa los valores de A y B es decir de las ovejas y de la puerta en donde toman los valores de cero AB=00(A=0 y B=0); La segunda columna al igual que la anterior representa los dos estados posibles de las variables donde AB=01(A=0 y B=1); Lo mismo para la tercera y cuarta columna AB=11(A=1 y B=1) y AB=10(A=1 y B= 0) respectivamente.
Posteriormente que llenamos nuestro mapa, hay que crear nodos agrupando en potencias de 2, los “unos” 1 que tengamos adyacentes de manera horizontal y vertical. 










 Ahora en cada grupo de unos se le asigna la unión (producto lógico) de las variables que se mantienen constante (ya sea uno o cero) ignorando aquellas que cambian.
Por ejemplo en nuestro mapa de karnaugh , nos vamos a la posición 0 1 1 que es donde tenemos nuestro primer 1 y nuestro nodo, entonces comparamos las variables A,B y C con cada uno de los nodos y solo las que permanezcan constantes, las tomaremos para formar la nueva función. 

Entonces quedaría así: 

Primera unión en la posición 0 1 1, con las variables C, A y B respectivamente.
Primera unión en la posición 1 1 1, con las variables C, A y B respectivamente.
Observamos que la variable C cambio cuando comparamos ambas posiciones y las variables A y B permanecieron constantes, entonces A y B las tomaremos para la nueva función.

Hacemos lo mismo en la segunda unión.
Segunda unión en la posición 1 1 1, con las variables C, A y B respectivamente.
Segunda unión en la posición 1 1 0, con las variables C, A y B respectivamente.
En esta segunda unión observamos que solo la variable B fue la que cambio, y las variables C y A permanecieron constantes, entonces son las que tomaremos para nuestra función.
La tabla siguiente muestra de manera mas clara el procedimiento anterior:












  






Como ya se dijo anteriormente solo se tomaron los valores que permanecieron constantes.
Nuestra nueva función ya reducida quedaría de la siguiente forma:
F= (A+B)(A+C) Agrupamos terminemos semejantes
F = A (B+C) y esta seria nuestra expresión ya reducida.

Ahora si queremos representar dicha función en un circuito o en algún lenguaje de programación, recordemos algunas de las puertas lógicas que vimos anteriormente en matemáticas discretas.
Si recordamos la puerta lógica AND indica una multiplicación y sus condiciones son: para que sus salida sea verdadera, por lo menos dos de sus entradas tendrán que ser verdaderas. Su representación es el siguiente:
 
La puerta lógica OR indica una suma y sus condiciones son: para que su salida sea verdadera, por lo menos una de sus entradas tendrá que ser verdadera. Su representación es la siguiente:


Nuestro circuito quedaria de la siguiente forma: 





 









Y de ahí solo quedaría a nuestro criterio si queremos implementarlo en un circuito electrónico o representar dicha función en un lenguaje de programación, en este caso, mas adelante lo representaremos en un lenguaje logico como lo es Prolog.

Referencias.

domingo, 31 de octubre de 2010

Porque no debemos utilizar la librería conio.h en ANSI C.


Hace rato que estaba programando en uno de nuestros lenguajes de programación favoritos, el ANSI C, por supuesto =) me surgió una duda interesante al utilizar ciertas librerias en una plataforma y otra. Como mi transición de Microsoft Windows a Linux Ubuntu fue un poco lenta, al quererme adaptar a otro entorno donde habrá “una mejor manera  de programar ” descubres ciertas cosas que no deberían de ser si estamos tan acostumbrados al uso de plataformas como Windows. A que me refiero con esto, para ser mas especifico, todos o la gran mayoría que crecimos utilizando sistemas operativos como Windows, al momento de introducirnos a la programación, como lo fue con ANSI C utilizando compiladores para dicha plataforma, se hacen uso de algunas librerías que no deberían ser utilizadas como es el caso de la tan conocida librería conio.h
Dado esto me surgió la curiosidad de investigar un poco, y redactar una breve reseña sobre porque no debemos utilizar tan conocida librería.

Nos trasladaremos a los años 80,s cuando una conocida compañía de software como lo es Borland. Fue fundada en 1983, en la actualidad, ya no es tal empresa, ya que fue vendida a una empresa llamada CodeGear(que sigue dando soporte y desarrollo a nuevos productos) que después fue vendida a otra empresa llamada Micro Focus, actualmente dicha empresa no es muy popular, esta dedicada al software empresarial.

Borland desarrollo varios compiladores para lenguajes como: Prolog, Pascal, Cobol, entre muchos otros, pero el mas popular para C y C++ fue el tan conocido Turbo C++.

Bueno ahora pensaran, que tendrá de malo que una empresa de software desarrolle compiladores para determinado lenguaje, pues bueno sabemos que en la actualidad para desarrollar nuevos productos (de cualquier área) se deben seguir ciertos estándares, conocidos por ser un conjunto de reglas a seguir. En la programación también existen estándares, pueden haber miles de compiladores para un lenguaje pero claro todos los compiladores deben seguir el estándar del lenguaje. A que voy con esto, que a la compañía Borland le dio igual seguir un estándar y en sus compiladores desarrollo librerías no estándares, es decir que esas librerías solo se utilizan en los compiladores que desarrollo dicha empresa, como la tan conocida librería conio.h.

Dicha librería se ha convertido para programadores acostumbrados a utilizar compiladores de Borland en una herramienta indispensable para desarrollar sus aplicaciones.
Esta librería contiene los prototipos de las funciones, macros, y constantes para preparar y manipular la consola en modo texto en el entorno de MS-DOS, dicho mas simple esta nos permite dar un “mejor formato” al texto en la terminal de MS-DOS, ya sea dandole color al texto o color al fondo, por mencionar un ejemplo simple.
Pero acaso ¿nosotros requerimos que nuestros programas desde la linea de comandos se vean bonitos?
Claro que no, lo importante es que de verdad hagan lo que deban de hacer, que funcionen y sean legibles.

Algunos de los comandos mas conocidos son: getch(), clrscr(), gotoxy(), textcolor(), y textbackground()

Aun así nosotros podemos sustituir estas funciones de la librería conio.h con otras funciones estándares.
  • Para sustituir clrscr(), solo necesitamos escribir system(“cls”); la cual está en iostream (es sin .h, se definiría así: #include iostream).
  • Gotoxy() es algo vago de usar pudiendo utilizar \n (espacio hacia abajo) y \t (espacio hacia la derecha) dentro de un printf();
  • Para sustituir getch(), solo necesitamos: cin.get(); la cual está en stdio.h. Si no funciona entonces tendremos que ponerla dos veces: cin.get();cin.get();,                                                                
    Y para ser honestos, creemos que se vera mucho mejor un programa, aunque sea con su típico fondo negro con letras blancas, que uno con letras amarillas con un fondo rosa :P

jueves, 21 de octubre de 2010

Presentacion Control de flujo secuencial.

Como sabrán, hace ya varias sesiones conocimos lo que era recursión y sobre sus distintas aplicaciones y usos.
Sabemos que hay otra manera también de aplicar secuencias de control, no solo utilizando recursión. Básicamente de esto consistieron las presentaciones de la sesión anterior, en donde a varios casos particulares, conocimos como se aplica el flujo de control.
Fueron varios los temas los que se presentaron.
Nosotros trabajamos con BFS-(Búsqueda en anchura.) Por sus siglas en ingles, se trata de un algoritmo de búsqueda en un grafo y su función principal radica en recorrer dicho grafo, nodo por nodo hasta llegar a su nodo de destino.
Estas son las diapositivas que utilizamos para la presentación, en este momento estamos trabajando con un caso practico, en donde profundizaremos un poco mas la aplicacion de dicho algoritmo.