lunes, 27 de diciembre de 2010

Ofuscando .NET

La ofuscación de código tiene cómo objetivo proteger la propiedad intelectual del software. Se trata de un proceso por el cual se hace incompresible (o casi) a  los humanos comprender el código.
Dado que es muy fácil transformar el MSIL (el código intermedio que se general al compilar en los lenguajes de .NET y que es luego interpretado por el CLR) en por ejemplo C#, muchos programadores ven la necesidad de proteger su código mediante la ofuscación.
Hay diversas herramientas disponibles en el mercado a diversos precios, afortunadamente existe una herramienta muy potente, que se integra perfectamente con VisualStudio y que es gratuita. Se trata de Eazfuscator.Net.
Una intefaz sencilla y amigable sumado a la posibilidad de lo que se denomina ofuscación declarativa mediante atributos (Declarative Obfuscation Using Custom Attributes).



La figura anterior muestra la forma de ofuscar un proyecto mediante un simple drag and drop.
Para descargarlos, probarlo y ver mas pueden ir a: http://www.foss.kharkov.ua/g1/projects/eazfuscator/dotnet/Default.aspx

miércoles, 13 de octubre de 2010

Parámetros Opcionales en C# 4

La nueva versión del lenguaje C# agrega la posibilidad de establecer métodos con parámetros nombrados opcionales. De esta forma puede evitarse tener que definir métodos sobrecargados que en realidad hacen los mismo.

Por ejemplo, para definir un método que recibe un string y un entero podemos tener el siguiente código:

public void recibedos(string cadena, int entero){

…..cuerpo del método

}

Ahora supongamos que queremos que el entero sea optativo. Para ello basta con asignarle un valor por defecto:

public void recibedos(string cadena, int entero=0){

…..cuerpo del método

}

De esta manera podemos invocar

recibedos(“una cadena”);

o

recibedos(“una cadena”, 7);

En el primer caso el parámetro entero toma el valor 0 indicado en su declaración (puede indicarse cualquier valor). En el segundo el parámetro recibe el valor 7.

C# 4 soporta también argumentos nombrados. Algo muy útil cuando se tiene por ejemplo un método como el siguiente:

public void haceralgo(int x=0, int y=1){

….cuerpo del método

}

En este caso tenemos dos parámetros opcionales la x y la y.  Es posible que quiera invocarse el método con sólo un valor para la x, con sólo un valor para y o con ambos o sin ninguno.

haceralgo(x:2);
haceralgo(y:3);
haceralgo(y:2,x:3);
haceralgo();

Todas las invocaciones anteriores son válidas, en el primer caso se usa el valor por defecto de y, en el segundo el valor por defecto de x, en el tercero se invirtió el orden (algo no recomendable pero posible) la y recibe 2 y la x 3. En el cuarto caso no se pasan parámetros y la rutina ejecuta con x e y usando sus valores por defecto.

miércoles, 16 de junio de 2010

Eiffel: forma iterativa cómo expresión lógica

En el artículo anterior vimos la nueva sintaxis para los ciclos llamada forma de iteración. Esta forma más compacta de expresar el ciclo (loop) tiene la ventaja de no evitar efectos laterales mediante la utilización implícita de un cursor nuevo.  Está característica hace a esta forma ideal para usarla como expresión lógica y por ende incorporarla a los contratos.

La forma de lograr expresiones lógicas a partir del ciclo es usando alguna de las dos notaciones alternativas para el cuerpo del ciclo en lugar de la palabra loop:

  • some expresión_lógica
  • all expresión_logica

Por ejemplo:

across mi_lista as  ic   all  ic.item.count > 3 end

En este caso tenemos un ciclo que recorre la lista y consulta cada elemento para ver si la propiedad count es mayor a 3. En caso de cumplirse para toda la lista el ciclo cómo expresión lógica es verdadero. En el caso de usar some en lugar de all el ciclo será verdadero si al menos un elemento cumple la condición.

La utilización de all o some como cuerpo del ciclo sólo es permitido si no hay parte de inicialización en el mismo (from).

Evidentemente esta nueva facilidad sintáctica soportada por contratos (por ejemplo no es posible modificar una estructura recorrida por la forma iterativa across, para ello debe usarse la forma tradicional loop) brinda muchas facilidades a los desarrolladores Eiffel.

martes, 1 de junio de 2010

Nueva construcción para ciclos en Eiffel: across

En el libro Algoritmos, Objetos y Estructuras de Datos se explica detalladamente la estructura de ciclo en Eiffel. Posteriormente a la publicación del libro el lenguaje se vio ampliado con la introducción de una variante que permite un modo de programación seguro,  mas conciso, mas abstracto sin perder las cualidades del calidad de la sentencia loop (invariante y variante de ciclo).
Describiremos entonces lo que llamamos forma de itereación (across), el cual nos permite especificar iteraciones en forma mas compacta. La única condición es que la iteración se debe realizar sobre una estructura que herede de la clase ITERABLE. Todas las estructuras significantes de EiffelBase se han modificado para heredar de ITERABLE.
Para ir al grano vemos como sería la iteración sobre una lista:

Este mismo ejemplo usando la forma tradicional se escribe:

across mi_lista as lc loop print (lc.item) end

from my_list.start until my_list.off loop print (my_list.item) my_list.forth end

Analicemos las partes en que se divide la forma de iteración. Comienza con la "parte de iteración”:


across mi_lista as lc

Esta parte establece cual es la estructura sobre la que va a iterar (mi_lista) y además el cursor a usar (lc). La forma de iteración utiliza un cursor externo creado especialmente para la iteración y cuyo alcance  es sólo en la iteración.
Luego de la parte de iteración tenemos la parte del cuerpo de la iteración:

loop print (lc.item)

Esta parte utiliza el cursor para acceder al elemento apuntado en cada momento de la iteración. Nótese que no hay referencia a mover el cursor para adelante ni a controlar el fin de la lista (mi_lista.off). cómo en el caso tradicional . Todo esto es abstraído por la construcción y evita de esta manera errores de programación al respecto.
Una diferencia muy importante es que la forma de iteración utiliza un cursor externo mientras la forma tradicional (cómo la hemos escrito) usa un cursor interno. La generación automática de un cursor externo es ventajosa porque permite que la iteración no cambie el estado de la lista. Eso nos permite tener activos varios recorridos al mismo tiempo sin  afectarse entre si.
Si el cursor se crea automáticamente ¿cómo atravesamos la lista al revés?, es decir de atrás para adelante.. Una característica importante de la clase ITERABLE es la rutina new_cursor la cual devuelve un cursor nuevo recién creado asociado a la estructura. Este cursor es de tipo ITERATION_CURSOR que a su vez hereda de ITERABLE por lo cual podríamos escribir:

across mi_lista.new_cursor.reversed as c loop print (c.item) end

En el próximo artículo veremos el uso de la forma iterativa como expresión lógica.

jueves, 13 de mayo de 2010

Ciclos y Gráficos usando Matlab

En este artículo saldremos un poco de la estructura del blog para referirnos a una herramienta muy utilizada para el procesamiento de imágenes y el cálculo y manipulación de datos matriciales.  Lo interesante es que permite comunicarse con otros lenguajes (como C#, Java, etc) a través de funciones de librería específicas que facilitan el trabajo

El tipo de datos fundamental en Matlab (y en Octave) es la matriz y existen muchísimas funciones que manipulan este tipo de dato. Pero hoy nos vamos a ocupar de algo menos común y más algorítmico: como realizar ciclos en Matlab/Octave y como aprovecharlos para realizar gráficos de diferentes funciones.

Algunos conceptos previos:
Operador ‘:’
Se trata de una de las formas de definir vectores y matrices más usada y más fácil de utilizar, dada la rápida visualización de la salida sin necesidad de ver el resultado:

octave> x=1:1:10;
octave> x

x =
1 2 3 4 5 6 7 8 9 10

De alguna manera, el : representa un rango, en este caso desde 1 hasta 10 y en el centro se coloca el paso (o sea con que incremento se llega desde 1 hasta 10). Por defecto el paso es 1 pero puede ser cualquier número entero o real, positivo o negativo:


octave> x=10:-1:1
x =
10 9 8 7 6 5 4 3 2 1


Gráficos
plot() crea un gráfico a partir de vectores y/o columnas de matrices, con escalas lineales sobre ambos ejes.
Por ejemplo, vamos a hacer un gráfico de la función 0.1 * |x| * sin(x)
Graficaremos usando valores para x entre -2pi y 2pi

  • Generamos el vector x entre -2p y 2pi

octave> x = -2*pi:0.1:2*pi;

  • Dibujamos:

octave> plot(x, abs(0.1*x) .* sin(x));


.* Recordar que * es el producto de matrices. No funcionará con vectores, mientras que .* es el producto miembro a miembro de los elementos de cada vector

fig1

Generalicemos nuestra función: a * |x| * sin(x) y graficamos dando 3 diferentes valores a la variable a. Por ejemplo:


octave> plot(x, abs(0.1*x) .* sin(x));
octave> plot(x, abs(0.2*x) .* sin(x));
octave> plot(x, abs(0.3*x) .* sin(x));

¿Cómo hacemos si queremos ver los tres gráficos en una misma pantalla?


octave> hold on;

hold es una función que permite agregar gráficos a una figura ya existente, respetando su contenido

Otras funciones útiles:

  • grid: Muestra una cuadrícula en la pantalla del gráfico. Usando grid  on se activa y con off se desactiva
  • title(‘titulo’): Coloca un título al gráfico
  • xlabel(‘leyeda x’): Coloca una leyenda al eje x
  • ylabel(‘leyeda y’): Coloca una leyenda al eje y


Por defecto, el color de las líneas del gráfico es rojo, pero eso se puede cambiar, así como también el estilo de las líneas. En las siguientes tablas se muestran las posibilidades de colores y estilos de líneas:

Símbolo

Color

y

Amarillo

m

Magenta

c

Celeste

r

Rojo

g

Verde

b

Azul

w

Blanco

k

Negro (por defecto)

Símbolo

Tipo de línea

.

Puntos

o

Con círculos

x

Marcas en x

+

Marcas en +

*

Marcas en *

s

Marcas cuadradas

d

Marcas en diamante

^

Triangulo apuntando arriba

Dibujemos, finalmente las 3 funciones en la misma hoja gráfica:

octave> hold on;

octave> plot(x, abs(0.1*x) .* sin(x));
octave> plot(x, abs(0.2*x) .* sin(x),’r+’);
octave> plot(x, abs(0.3*x) .* sin(x),’mo’);

 

fig2

En la siguiente entrega, nos ocuparemos de los ciclos y tendremos más ejemplos.

jueves, 29 de abril de 2010

Novedades en C# 4.0

El lenguaje de programación C# sigue evolucionando junto con el framework .Net. A la par del lanzamiento de la nueva versión de .NET  del VisualStudio 2010 surge la nueva versión de C# la 4.0.

El lenguaje sigue evolucionando con nuevas características, en este artículo mencionaremos algunas de ellas.

Se introduce una nueva palabra clave dynamic, utilizada para definir tipos dinámicos. Los tipos dinámicos son utilizados cuando, por ejemplo, se quiere acceder a código creado con un lenguaje dinámico como Iron-Python . Esta palabra clave le dice al compilador que el tipo de  los objetos se definirá en tiempo de ejecución y puede de esa manera responder a invocaciones dinámicas de métodos.

El siguiente código nos muestra un ejemplo:

dynamic miObjeto = ObtenerObjetoDePython();
miObjeto.Propiedad = “dato”
miObjeto.MetodoDinamico();

En tiempo de ejecución se definirá el tipo de “miObjeto” y el ambiente de run-time descubre las propiedades y genera el enlace dinámico al código correspondiente. El peligro, como con todo lenguaje sin tipificación fuerte, es que el método invocado no este definido en cuyo caso se produce una excepción en tiempo de ejecución. El uso que debería descartarse por completo para este tipo de declaración es usar una misma variable para diferentes tipos de objetos. Eso si que es feo.

Otra de las novedades son los parametros con nombre y variables en métodos. Es posible darle nombre a los parámetros y hacerlos opcionales. Por ejemplo:

public void unMetodo(int par1, String par2="valordefecto", decimal par2=99.85){

//Hacer algo

}

En la declaración precedente hay dos parámetros con nombre y además con valores pode defecto. Esto permite transformarlos en opcionales.

Si tenemos un objeto digamos objetoA que sea de la misma clase que unMetodo, podemos realizar las invocaciones de la siguiente forma

 

objetoA.unMetodo(4,”unvalor”,19.98);

objetoA.unMetodo(4,”unvalor”);

objetoA.unMetodo(4,par2:19.98);

En el último caso se nombra explícitamente el parámetro ya que en esa posición el método tiene declarado un parámetro de tipo string. Es decir los parámetros con valores por defecto son opcionales en la invocación pero si hay diferencia de orden o se saltea alguno deben nombrarse explícitamente para evitar errores de compilación.

Otra novedad es la covarianza de estructuras genéricas pero eso daría para un artículo entero.

lunes, 19 de abril de 2010

Object-Test y tipos asignados: Void.Safety en Eiffel

En un artículo anterior describimos el mecanismo de CAP utilizado para conseguir sistemas void-safety en Eiffel. Ahora describiremos las otras herramientas tipos asignados y la instrucción object test
Object test provee un mecanismo de identificación de tipos en tiempo de ejecución (reemplaza también a la construcción anterior de Eiffel llamada intento de asignación). Básicamente verifica que una referencia tenga asignado un objeto de un tipo determinado.  La sintaxis es la siguiente:

if  attached {T} exp as l then
 -- Operaciones sobre l
end

La expression attached {T} exp as l   es una expression logica (booleana) que es verdadera cuando exp es una referencia que tiene asignado un objeto conformante con el tipo T.   La nueva variable l con alcance en el if pasa a tener asignado el objeto denotado por exp.          
Entonces es seguro la siguiente secuencia:

if attached x as l then
   l.f (a)
end

Dado que f(a) se invoca sobre l y sólo cuando este tiene un asignado un objeto (el mismo que referencia x en el momento del test). En el ejemplo último, el tipo T es implícitamente el tipo estático de x. El uso de l es obligatorio para void-safety porque evita problemas en caso de que en un ambiente multihilo sea modificado el valor de exp.

El otro mecanismo que queda por ver el de tipos asignados. Este mecanismo es una extensión del sistema de tipo de Eiffel. Previamente cualquier variable de un tipo de referencia podía tener asignado void. Así todas las variables eran consideradas desasignables (detachables). Ahora el standard de Eiffel soporta tipos asignados (attached) o desasignables (detachables). Si una variable es declarada como attached entonces el compilador previene que dicha variable puede asignársele Void o asignarse alguna cosa que pueda ser void.

Ejemplos:
x: attached STRING

y: detachable STRING

En el primer caso la x siempre tendrá un objeto asignado y nunca podrá darse un error de null reference, mientras en el segundo caso a la y se le puede asignar Void y la garantía de void-safety debe proporcionarse por los otros medios mencionados.
Para garantizar este mecanismo hay reglas que el compilador debe asegurar. Por ejemplo es posible asignar x a y pero no y a x.
Es necesario utilizar un mecanismo de inicialización que prevenga que una variable de un tipo attached no sea asignada. Para casos como enteros o valores lógicos Eiffel ya proveía un mecanismo de inicialización (por ejemplo los enteros son inicializados en cero) Los tipos de referencia (detachables) son asignados con Void, pero esto no sirve para los tipos de referencia attached. Para resolver el problema se utiliza el concepto de variable propiamente iniciada (properly set) que significa que a la variable le fue dado un valor distinto de Void . Se usa la siguiente regla:

Regla de inicialización de tipos asignados:
Si un programa usa una variable en cierta posición una de las siguientes propiedades debe cumplirse:

  •  La variable es propiamente asignada en esa posición. Esto se aplica a ambos tipos de variables: atributos y variables locales de una rutina.
  • La variable es un atributo y es propiamente inicializada al final de todo procedimiento de creación de la clase.

De esta manera completamos una visión general de los mecanismos de Eiffel para lograr evitar el problema de la null-reference. Cabe indicar que el compilador o el entorno de desarrollo traen facilidades para ir incorporando estos mecanismos. Por ejemplo es posible configurar que todos los tipos sean attached o detachable por defecto.

martes, 13 de abril de 2010

Nuevo sitio de Inteligencia Artificial


La Inteligencia Artificial es una rama de las ciencias de la computación que tiene objetivos científicos e ingenieriles. Por un lado comprender el funcionamiento del cerebro humano y la inteligencia, estudiar mecanismos de comportamiento inteligente y por otro construir software que pueda exhibir comportamiento inteligente. Las aplicaciones de la Inteligencia Artificial y sus subcampos van desde robótica, reconocimiento de imagenes hasta control inteligente de dispositivos.
Un nuevo sitio dedicado al tema y en donde es posible consultar un libro en línea (e-book) fue desarrollado por Uppersoft para que los interesados en el tema puedan introducirse.
Pueden acceder a el en el siguiente enlace http://www.smartcomputing.com.ar Ya están los primeros capítulos del libro Fundamentos de Inteligencia Computacional (escrito por Gerardo Rossel) en línea.

lunes, 5 de abril de 2010

Nueva versión en formato Digital

Dado los pedidos de lectores que nos comentaban los costos de envío a sudamerica hemos decidido lanzar una versión del libro Algoritmos, Objetos y Estructuras de Datos Una introducción a la programación por contratos en formato digital.
Para adquirirlo hagan click en el siguiente botón:
Support independent publishing: Buy this e-book on Lulu.



lunes, 22 de marzo de 2010

Patrones de Asignación Certificados (Certified Attachment Pattern)

En el artículo anterior sobre  Eiffel: void-safety dimos los conceptos básicos que implementa el lenguaje Eiffel para conseguir sistemas que no produzcan el famoso error de referencia nula. O sea cuando se hace una llamada a una entidad que apunta a Void.
La estrategia de Eiffel se basa en tres mecanismos: Patrones de Asignación Certificados, Tipos Asignados y Object Test.
En el articulo de hoy vamos a explicar el primer mecanismo, el de Patrones de Asignación Certificados o CAP. La idea es que en ciertos patrones de código se sabe certeramente que una referencia no puede ser Void. Un CAP es simplemente uno de estos patrones identificado. Por ejemplo el siguiente patrón simplemente verifica que x no sea Void:



if x /= Void then
    -- Hacer cualquier cosa menos asignar algo a x
    x.f (a)
end



Si garantizamos que x no se le asigna nada entonces es segura la invocación x.f(a) dado que x no es Void. Este código es un CAP para x.  Para que esto valga (lo mismo con otros CAPs) x debe ser una variable local o un argumento, no puede ser un atributo de la clase. Es lógico esta prohibición dado que un atributo podría ser asignado a Void al invocar una rutina. Lo que decimos es:


Una llamada x.f(...) donde x es un argumento formal o una variable local de una rutina es void-safe (segura para void) si la llamada verifica que:

  • Aparece en el alcance de un testeo de void involucandro a x
  • No es precedida, en dicho alcance, por una asignación para x.


En siguientes artículos continuaremos analizado esta interesante propiedad implementada en el lenguaje Eiffel que nos permite tener sistemas orientados a objetos seguros para void.

martes, 16 de marzo de 2010

Eiffel: Void-safety. No más errores de null reference!!

Al momento de escribir el libro todavía no estaba implementado completamente el mecanismo que lograba void-safety en Eiffel. El problema que se evita es conocido como excepción por null reference o void call (según el lenguaje y entorno).
El problema se presentaba cuando se realiza una llamada de la forma: x.f(a)si  x era una referencia a Void (null reference). La tipificación estática no es suficiente, ya que ésta asegura (en el ejemplo anterior) que existe una feature f aplicable a x. Lo que garantizaría la void-safety es que en el momento de la ejecución haya un objeto asignado a x. En .Net este error es comúnmente encontrado mediante una excepción con el mensaje: "Object reference not set to an instance of an object". El mecanismo que logra evitar este problema esta completamente implementado a partir de EiffelStudio 6.4. 
Recordaran que en Eiffel existen dos clases de tipos: expandidos y de referencia. Con los primeros no hay problema por su propia semántica, siempre hay un objeto. El problema podría presentarse solamente con los tipos no expandidos. 
En resumen, lo que estamos diciendo, es que una entidad puede ser asiganda (attached) o  no asignada (detached) en este último caso es Void (null en otros lenguajes). Una llamada a una entidad no asignada provoca un error en tiempo de ejecución. Eiffel implementa un mecanismo para resolver este problema.
La asignación es vista (hasta ahora) cómo una propiedad en tiempo de ejecución, es decir una entidad en algún momento de la ejecución del programa puede estar asignada o no asignada. Para lograr la void-safety ampliamos este concepto de asignación para considerar también la asignación estática. Este último tipo de asignación puede ser evaluado en tiempo de compilación. El mecanismo implementado asegura que se cumpla una importante propiedad: la consistencia de asignación.


Consistencia de Asignación: si una entidad x es estáticamente asignada sus valores posibles en tiempo de ejecución son dinámicamente asignados.


Para garantizar entonces que no haya llamadas a void (void call) se incorpora al lenguaje la siguiente regla:


Regla de void-safety: Una llamada de la forma x.f(a) es permitida solamente si x es estáticamente asignada.


Al garantizar que x es estáticamente asignada, por la regla de la consistencia de la asignación x no puede asumir valores void en ninguna llamada.


Para garantizar la void-safety Eiffel utiliza una estrategia basada en tres mecanismos:

  • Patrones de asignación certificados (Certified Attachment Patterns o CAPs), que básicamente representan esquemas de código que el compilador puede garantizar ser seguros.
  • Tipos asignados. Son tipos que no pueden tener valores nulos (void). 
  • Instrucción "Object Test". Esta instrucción permite a los programadores tratar de forma especial los valores nulos

En los siguientes artículos iremos describiendo cada uno de estos mecanismos en detalle.

sábado, 6 de marzo de 2010

Tabla de Contenidos

Este blog está dedicado al libro Algoritmos, Objetos y Estructura de Datos. Una introducción a la Programación con Contratos (Gerardo Rossel - Andrea V. Manna 2009). Trataremos temas relacionados al libro, ejercicios, erratas, etc.
Para los que aún no tienen el libro a continuación la tabla de contenido:


1. Conceptos Introductorios
1.1. Un enfoque orientado a objetos
1.2. ¿Qué es un algoritmo?
1.3. Compilación de Programas
1.4. Códigos ASCII y UNICODE
1.5. Máquinas Virtuales
1.6. Algoritmos y sentencias
1.6.1. Decisión
1.6.1.1. Estructuras de decisión anidadas
1.6.1.2. Estructuras de selección y lenguajes
1.6.1.3. Estructura de decisión generalizada o múltiple
1.6.2. Repetición o Iteración
1.6.2.1. Estructura repetir-hastaque
1.6.2.2. Estructura mientras-hacer-finmientras
1.6.2.3. Estructura para-hacer-finpara
1.6.2.4. Estructuras de repetición y lenguajes
1.7. Ejercicios
2. Primeros pasos con Objetos
2.1. ¿Qué son los objetos?
2.2. Sentencias.
2.3. Nuestro primer programa: Hola Mundo
2.4. Trabajando con EiffelStudio
2.5. Creación de objetos
2.6. Relación entre variables y objetos
2.7. El objeto Current
2.8. Código C#
3. Tipos de Abstractos de Datos
3.1. El método axiomático
3.2. El TAD CUENTA_BANCARIA
3.3. El método de las poscondiciones.
3.4. Ejercicios
4. Clases y Objetos
4.1. TAD y Clases
4.1.1. Traslación de las operaciones de TAD
4.2. Rutinas y Atributos
4.3. El concepto de propiedad
4.4. Pasaje de argumentos
4.4.1. Pasaje de Argumentos por Valor
4.4.2. Pasaje de Argumentos por Referencia
4.4.3. Pasaje por Copia/Restauración
4.4.4. Pasaje de Argumentos por Valor Constante
4.4.5. Pasaje de Argumentos por Nombre
4.4.6. Pasaje de Argumentos en Eiffel
4.4.7. Pasaje de Argumentos en C#
4.5. Clusters y espacios de Nombres
4.6. Accesibilidad
5. Contratos
5.1. Precondiciones
5.2. Poscondiciones
5.3. Invariante de Clase
5.4. Que no son las aserciones
5.5. Corrección de ciclos
5.6. La instrucción check
5.7. Monitoreo de aserciones
5.8. Vista de contrato
5.9. Ejercicios
6. Estructuras de Datos (primera parte)
6.1. Clases Genéricas
6.1.1. Clases genéricas en C#
6.2. Arreglos
6.2.1. Creación de un arreglo
6.2.2. Acceso y notación bracket
6.2.3. Arreglos en C#
6.3. Pilas y Colas
6.4. Listas
6.4.1. Movimiento del Cursor
6.4.2. Modificación de la lista
6.5. Implementaciones de Listas
6.5.1. Listas encadenadas
6.5.2. Listas doblemente encadenadas
6.5.3. Operaciones sobre Listas
6.6. Tuplas
6.7. Iteradores
6.8. Estructuras en C#
6.9. Ejercicios
7. Complejidad Algorítmica
7.1. Análisis de Algoritmos
7.2. La notación “Big O”
7.3. Complejidad de un algoritmo
7.3.1. Comparando complejidades
8. Algoritmos: Recursividad
8.1. Características
8.2. ¿Iteración ó Recursión?
8.3. Contratos y recursividad
8.4. Ejercicios
9. Algoritmos: Ordenación y Búsqueda
9.1. Búsqueda
9.1.1. Búsqueda Secuencial o Lineal
9.1.2. Búsqueda Binaria
9.1.3. Algoritmos de Búsqueda en C#
9.2. Ordenación
9.2.1. Ordenación por selección directa
9.2.2. Ordenación por el método de Burbujeo
9.2.3. Ordenación rápida ó Quicksort
10. Introducción a la Herencia
10.1.¿Qué es Herencia?
10.2.Herencia un ejemplo
10.3.Polimorfismo
10.4.Conformidad de tipos
10.4.1. El tipo Current y los tipos anclados
10.4.2. Herencia no conformante
10.5.Invocando al antecesor
10.6.Herencia en C#
10.7.Testeo de objetos y asignación condicional
10.8.Ejercicios
11. Tipos, rutinas y objetos
11.1.Introducción
11.2.Agentes en Eiffel
11.2.1. Tipos de los agentes
11.2.2. Llamando a un agente
11.2.3. Agentes e iteradores
11.3.Delegados y Eventos en C#
11.3.1. Delegados
11.3.2. Eventos
11.4.Tipos de Referencia y Tipos expandidos
11.4.1. Tipos Básicos
11.5.Tipos de Valor en C#
11.5.1. Tipos simples
11.5.2. Tipos enumerados y estructuras
11.5.3. Tipos anulables
11.5.4. Boxing y Unboxing
11.6.Rutinas “Once” y Constantes
11.7.Miembros y Clases Estáticas en C#
11.8.Ejercicios
12. Arboles
12.1.¿Qué es un Árbol?
12.2.Árboles binarios
12.2.1. Árbol Binario en C#
12.3.Recorrer un árbol binario
12.3.1. Recorrido en pre-orden
12.3.2. Recorrido en-orden
12.3.3. Recorrido post-orden
12.3.4. Complejidad de los recorridos
12.4.Árboles binarios de búsqueda
12.4.1. Insertar un elemento
12.4.2. Borrar un elemento
12.5.Ejercicios
13. Herencia Parte II
13.1.Introducción
13.2.Redefinición: Covarianza
13.3.Renombrado y otras operaciones
13.3.1. Fusión de abstracciones
13.3.2. Choque de nombres
13.4.Herencia repetida
13.4.1. La clausula select.
13.4.2. Compartir o replicar
13.5.Congelar características y clases.
13.6.Contratos y herencia
13.6.1. Invariante en herencia
13.6.2. Pre y poscondiciones
13.7.Generalidad restringida
13.8.Interfaces en C#
13.9.Ejercicios
14. Grafos
14.1.Introducción
14.2.Definiciones
14.3.Implementación de Grafos
14.3.1. Representación con lista de adyacencia
14.3.2. Representación por matriz de adyacencia
14.3.3. Implementación con lista de ejes y vértices.
14.4.Algoritmos sobre grafos
14.4.1. Profundidad primero
14.4.2. Ancho Primero
14.4.3. Camino más corto: el algoritmo de Dijkstra
14.5.Ejercicios
15. Diseño Orientado a Objetos
15.1.Introducción
15.2.Elicitación de Clases
15.2.1. Casos de Uso
15.3.BON, UML: describiendo Clases.
15.3.1. Diagramas de Clase
15.3.2. Diagrama de Secuencias
15.3.3. Eso no es todo.
15.4.Un pequeño problema
15.5.Ejercicios