Archivo

Archive for 30 septiembre 2007

ManPages en español

septiembre 30, 2007 2 comentarios

Imagen alojada en imaXenes.com
Una herramienta muy potente y que no todos la aprovechamos como se debería es la ayuda del sistema, o más conocida como “man”

guille@leinad-desktop:~$ man ls

Pero si no estamos familiarizados con el idioma inglés que es en el que están escritas las páginas del manual, es lo mismo que nada.

Por esa razón vamos a instalar las páginas en español.
guille@leinad-desktop:~$ sudo apt-get install manpages-es
guille@leinad-desktop:~$ sudo apt-get install manpages-es-extra

guille@leinad-desktop:~$ man cp
Y debería mostranos la pagina de ayuda de “cp” en español. 🙂
Pero si llegara a pasar que no nos está tomando los caracteres especiales del idioma, como por ejemplo los acentos tenemos que solucionarlo. Por ejemplo: Si en vez de mostrar último muestra algo como último

Solución:

  1. Editamos los siguientes archivos:

    sudo vim /var/lib/locales/supported.d/es
    sudo vim /var/lib/locales/supported.d/local

    Agregandoles al mismo las siguientes líneas:
    es_ES@euro ISO-8859-15
    es_ES ISO-8859-1
  2. Abrimos y editamos el archivo y le agregamos:

    guille@leinad-desktop:~$ vim .bashrc
    # Esto es para mostrar correctamente los acentos
    alias man='LC_ALL=es_ES@euro man'
  3. Reconfiguramos los locales de idiomas.

    guille@leinad-desktop:~$ sudo dpkg-reconfigure locales

Solo nos resta cerrar la consola y abrir nuevamente para ver los resultados, si todo anda bien podríamos apreciar los acentos de forma correcta en las man.

Categorías:linux, vim

¿Cuál no anda?

septiembre 29, 2007 Deja un comentario

Este post se lo dedico a Humitos, ya que reafirmo que lo tuyo con lo cables es un tema menor en comparacion de los que tendrán lo administradores de éstas redes. Esto lo podemos catalogar como una maraña de cables 🙂

Mas aquí

Categorías:General

Recursividad

septiembre 28, 2007 3 comentarios

Siguiendo con el estudio para el parcial de Diseño e Implementación de Estructuras de Datos, vamos a ver la Recursión.
Se dice que un proceso es recursivo si forma parte de sí mismo, es decir, que se define en función de sí mismo. La recursión aparece en la vida diaria, en problemas matemáticos, en estructuras de datos y en muchos otros problemas. Es un proceso extremadamente potente, por lo que hay que saber cuándo y cómo aplicarla.

Un método recursivo es un método que, directa o indirectamente, se hace una llamada a sí mismo

En las aplicaciones prácticas, antes de poner en marcha un proceso recursivo es necesario demostrar que el nivel máximo de recursión (que es es el número de veces que se va a llamar a sí mismo), es no solo finito, sino realmente pequeño. La razón es que necesitaremos una cierta cantidad de memoria para almacenar el estado del proceso cada vez que se abandona temporalmente, debido a una llamada para ejecurtar un proceso de sí mismo. El estado de cálculo en curso hay que almacenarlo para recuperarlo cuando se acabe la nueva ejecución del proceso y haya que reanudar la antigua.
Por esta razón a la existen 4 reglas fundamentales de la recursión, que tenemos que tener en cuenta a la hora de realizar nuestro algoritmo.

  1. Caso Base: se debe tener siempre, al menos un caso base que pueda resolverse sin recursión.
  2. Progreso: cualquiera llamada recursiva debe progresar hacia un caso base.
  3. Puede creerlo: asuma siempre que toda llamada recursiva interna funciona correctamente.
  4. Interes compuesto: nunca duplique el trabajo resolviendo la misma instancia de un problema, en llamadas recursivas separadas.

Tipos de recursión según su complejidad

  1. Resursión lineal: Un método recursivo es lineal, si como máximo tiene una llamada recursiva por rama del condicional, de manera que la cantidad de llamadas recursivas puede calcularse como una función lineal que dependerá de la velocidad con la cual progresa hacia el caso base. Ésta a su vez la subdividimos en:
    1. Resursión por la cola: es cuando la llamada recursiva se hace al final del método, no quedan operaciones pendientes sobre los datos, de manera que no hace falta representar con una pila las variables de cada llamada, y el método recursivo lo podriamos transformar tranquilamente en un bucle iterativo.
    2. Veamos el ejemplo del :Máximo común divisor entre a y b


      def mcd( a, b):
      if( b==0):
      return a
      else:
      return mcd( b, a%b)

    3. Recursión no por la cola: es cuando después de ejecutar todas la llamadas recursivas el método debe realizar una operación pendiente para completar le proceso.
    4. Veamos el ejemplo: Obtener el factorial de un número


      def factorial(n):
      if( n==1):
      return 1
      else:
      return n * factorial(n-1)

      Como vemos luego de ejecutar las llamadas recursivas debemos realizar la operacion “*”.

  2. Recursión no lineal: Un método recursivo es no lineal, si hay más de una llamada recursiva por rama del condicional.
    1. Recursión en cascada: es cuando en cada rama hay mas de una llamada a la función recursiva,su complejidad en término de llamadas recursivas será una función exponencial de la profundidad del árbol de las llamadas.
    2. Veamos el ejemplo: Obtener el n-ésimo valor de la serie de Fibonacci


      def fibonacci(n):
      if( n<=1):
      return 1
      else:
      return fibonacci(n-1) + fibonacci(n-2)

    3. Recursión anidada: es cuando alguna llamada recursiva recibe como parámetro a una llamada recursiva, su complejidad en término de llamadas recursivas resultará mucho más dificil de calcular.
    4. Veamos el ejemplo: Función de Ackermann


      def Ackerman(m, n):
      if (m == 0):
      return n+1
      elif (m > 0 and n == 0):
      return ackermann(m-1, 1)
      elif (m > 0 and n > 0):
      return ackermann(m-1, ackermann(m, n-1))

  3. Recursión mutua: se da cuando dos funciones son recurrentes entre sí.
  4. Veamos el ejemplo: decir si es par o impar el parámetro.


    def impar(n):
    if (n==0):
    return false;
    else
    return par(n-1)

    def par(n):
    if (n==0):
    return true
    else:
    return impar(n-1)

Me parece que los aburrí con tanta teoría :)... Falta solo un poco. Que mas podemos comentar de la Recusión?, como la implementamos?. Existen distintas estrategias, trataré de explicar un poco de cada una:

  1. Divide y vencerás: dijo Napoléon Bonaparte 🙂
    Estos algoritmos constan de dos partes:

    1. Dividir: se resuleven recursivamente problemas más pequeños (exepto los del caso base).
    2. Vencer: la solución al problema original se consigue a partir de las soluciones a los subproblemas.
  2. Estos algoritmos son generalmente muy eficientes y tienen menos llamadas recursivas. Por lo general el Orden de éstos algoritmos es del O(N log N).

  3. Programación dinámica: es la técnica que evita la explosión recursiva guardando respuestas en una tabla. Esta estrategia de Agarra todo lo que puedas es la fuente el nombre de esta clase de algoritmos. Resulta agradable que un problema se pueda resolver usando un algoritmo devorador, ya que entonces el algoritmo se suele acercar bastante a nuestra intuición y además el código producido resulta comprensible. Pero como todo no es color de rosas, no siempre funcionan bien.
    El truco está en guardar las soluciones de los subproblemas en un vector.
  4. Algoritmos de vuelta atrás: usan la recursión para probar sistemáticamente todas las posibilidades

Para terminar un buen ejemplo: ¿Qué es la Recursividad?

Categorías:Programacion, python

Código Abierto ó Código Propietario?

septiembre 28, 2007 Deja un comentario

Si te dan a elegir entre un desarrollo de código propietario y otro de código abierto, elige el segundo, porque se comprobó que tardarás menos, incluso días menos, en hacer bien tu trabajo.
En el software privativo el tiempo medio para resolver el problema en una aplicación es de 6,9 días para los desarrolladores empresariales y 6,7 días para los vendedores de software; el 10% de esos casos necesitan unos 10 días para ser resueltos, indica el estudio.

En cambio los desarrolladores de código abierto El tiempo medio entre que se descubre que existe un problema serio en el software y se resuelve es, en el 36 por ciento de los casos, menor a las ocho horas. Sí, sí. Horas. No días. No semanas.

¿Esto quiere decir que el software de código abierto es mejor?.
No soy quien para contestar ésto, solo doy una humilde opinión. Es mejor si consideramos que su transparencia y disponibilidad permite que los fallos puedan detectarse más rápida y fácilmente. En el proceso, además, no se necesita que sea una persona particular la que lo encuentre y lo notifique, sino que es la comunidad la que apunta las soluciones. Y en el software privativo al ser su código cerrado, solo los que participan de ese proyecto tendrán disponibles los materiales para realizar la búsqueda y no es tan fácil ver u entontrar los errores.

Además, la ventaja de que estos fallos se solucionen antes no repercute sólo a los desarrolladores. Todos los usuarios nos beneficiamos con la rapidez en la respuesta.

Para ver más

Categorías:General, linux, Programacion

Fósil marino multicolor

septiembre 27, 2007 Deja un comentario

El Museo de Historia Natural de Nueva York exhibe desde este miércoles un ejemplar de fósil marino de 80 millones de años de antigüedad que, además de contar con unas proporciones extraordinarias, tiene la particularidad de ser multicolor.

Categorías:General

Análisis de algoritmos

septiembre 27, 2007 3 comentarios

Imagen alojada en imaXenes.comEstoy leyendo sobre este tema porque la semana que viene tenemos el primer parcial de “Diseño e Implementación de Estructuras de Datos”, y es una de las unidades que comprende el examen, ésta junto a la de Recursión son las más interesantes, y útiles a la hora de llevar a cabo la programación.

En que consta este paradigmático tema?.
Cuando ejecutamos un programa, sobre una cantidad de datos debemos estar seguros de que el programa termina en un tiempo razonable, independientemente de la metodología empleada ( POO, Lógica, Procedural, etc.), y del lenguaje utilizado ( Python, Java, C++, etc.). Para ir decubriendo esto tenemos que en primera instancia conocer qué es un algoritmo.
Un algoritmo es un conjunto de instrucciones claramente especificadas que el ordenador debe seguir para resolver un problema, en un tiempo finito.

El análisis de algoritmos es el proceso que empleamos para determinar la cantidad de recursos (tiempo, espacio, etc.), necesarios para la ejecución de un algoritmo en particular. Siendo el tiempo de ejecución una función del tamaño de entrada, puede ser lineal, cuadrática, cúbica o logarítmica. El valor exacto de esta función dependerá de más factores, tales como la velocidad de la máquina, la calidad del compilador, y en alguno casos la calidad del programa.Lo que nosotros vamos a tratar de medir es el índice de crecimiento de éstas funciones.
De las funciones que mencionamos, la lineal representa el algoritmo más eficiente. Por esta razón trataremos que nuestros algoritmos según sea el caso se comporten como una función lineal.

Incluso los trucos de programación más inteligentes no pueden hacer rápido un algoritmo ineficiente. Por tanto, antes de perder el tiempo intenteando optimizar un código, debemos tratar optimizar el algoritmo.

Hay muchos algoritmos radicalmente diferentes ( en términos de eficiencia), que pueden ser utilizados para resolver distintos problemas. Podemos decir que en primera medida, tratamos de utilizar el algoritmos de fuerza bruta que es el más simple de implementar, pero también el menos eficiente.

Supongamos el siguiente ejemplo:
Dado un vector A con n enteros, hallar el mínimo valor de A
¿Cómo lo resolvemos?.
Opción 1:
def minimo_1(A):
....min = A[0]
....for i in vector:
........if(min < i):
............min = i
....return m

Opción 2:
def minimo_1(A):
....A.sort()
....return A[0]

Cuál es más complejo?, por qué?
Para responder adecuadamente esto tenemos que tener en cuenta los Órdenes de Complejidad, y en particular nosotros vemos Reglas generales para la notación O, ésta notación se puede usar para clasificar las funciones de acuerdo a la tasa de crecimiento. Podemos decir que la opción uno es O(N), “del orden N”, decimos ésto porque en el peor caso el mínimo valor se encontrará en el último lugar.
Ahora se preguntarán que si el arreglo A, crece en gran tamaño, nos convendría hacer que nuestro algorítmo se comporte en vez de linealmente, logarítmicamente. Yo les diría que si, pero en éste ejemplo en particular el arreglo – en principio viene desordenado- y por eso una Búsqueda Binaria ó Dicotómica no nos serviria. Tendríamos que estudiar si nos conviene ordenar y buscar ó simplemente buscar linealmente. Pero el mejor comportamiento para ordenar (si no se aprovecha la estructura de las claves) es O(n log n). Los algoritmos más simples son cuadráticos, es decir O(n²). Los algoritmos que aprovechan la estructura de las claves de ordenamiento (p. ej. bucket sort) pueden ordenar en O(kn) donde k es el tamaño del espacio de claves. Como dicho tamaño es conocido a priori, se puede decir que estos algoritmos tienen un desempeño lineal, es decir O(n).
Que es lo que opinan?.

La regla más importante es:
“El tiempo de ejecucion de un bucle es como mucho el tiempo de ejecución de las instrucciones dentro del bucle (incluyendo los test) multiplicado por el número de iteraciones”

Una vez que hemos efectuado el análisis de un algoritmo, queremos ver si es correcto y tan bueno como sea posible. Una forma de hacerlo es implementar el programa y ver si el tiempo de ejecución observado empíricamente se ajusta con el tiempo de predicho por el análisis.

Para terminar mi resumen, quiero aclarar que esto es una herramienta más, es muy efectiva, pero es importante conocer sus limitaciones. No es apropiado para pequeñas cantidades de datos, para ésto utilizamos el algoritmo más simple.

Es un tema que presta a la discución, sanamente no?. Pero se pueden debatir distintas metodologías para implementar sobre un mismo problema.

Referencias:
Análisis de Algoritmos
Tutorial
Algoritmos de Ordenamientos

Categorías:Java, Programacion, python

Bug en Exel 2007

septiembre 26, 2007 1 comentario

El otro día sentí el comenterio sobre este bug, pero como no tengo Exel 2007 no lo puedo comprobar personalmente, para ver más te dejo este link .
Realizen la siguiente operación en una celda:
=850*77.1 lo cual debería devolver como resultado 65,535, pero en realidad lo que está devolviendo esa operación es 100,000.

Categorías:General