Automágica: durante 2017 estoy trabajando bastante en Automágica, mi software para editar libros: Más información - Posts relacionados

Mi primer clase en la universidad

El lunes por la noche dicté mi primer clase en la universidad. Si bien colaboro con la cátedra de Comunicaciones desde hace 2 años (cuando cursé la materia), soy oficialmente ayudante de cátedra desde el 1º de Abril del año pasado y nunca había dado una clase. Hasta ahora me había encargado de desarrollar herramientas (software) para que usen los alumnos al estudiar determinado tema (ver más).

No fue la primer vez que hablaba en público, ya había dado un par de charlas en congresos de Software Libre, pero un movido fin de semana anterior y poco tiempo para prepararme hizo que el lunes antes de llevar a cabo mi tarea me sienta un poco nervioso.

Ya que el profesor actual (Gabriel Filippa) da clases con slides, yo preparé las mías. El tema desarrollado fue: Capa de Enlace (para los que no estén familiarizados con lo que significa, les cuento para el estudio de las redes de computadoras se suelen organizar conceptualmente todos los elementos interviniéntes en 7 capas, la 2º de abajo para arriba, siendo la primera la capa física, es la de enlace: capa de enlace).

Las slides eran muy sencillas, tenían las ideas principales que quería desarrollar más ejemplos que quería evitarme tener que copiar en el pizarrón. Pero.. (Ley de Murphy) cuando iba a empezar la clase el cañón no andaba. Luego de unos 20 minutos intentando que ande ya se me habían ido todos los nervios y ya quería empezar. Dibujé en el pizarrón algunas cosas que iba a necesitar más tarde y justo antes de empezar el cañón anduvo.

La experiencia de dar la clase me gustó mucho, era unos 60 alumnos y casi todos prestaban atención. Algunos incluso anotaban :D. La clase fue dinámica, hubo bastante interacción con los chicos y creo que eso ayudó a que sea amena para todos (para ellos y para mi).

Comunicaciones es una materia cuatrimestral y este cuatrimestre ya está llegando a su fin así que creo que la próxima oportunidad será el año que viene.


Firefox Search Engine en 5 minutos

¿Querés crear un motor de búsqueda de Firefox para tu sitio web? Esta receta es para vos.

Adrián tiró el desafío en la lista de Gleducar. Uno de los links dados como pista fue:

http://developer.mozilla.org/es/docs/Creaci%C3%B3n_de_plugins_OpenSearch_para_Firefox

Puede seguirse sin problemas para generar el archivo xml que describe al plugin, pero me hubiese venido bien encontrar un motor.xml de ejemplo. Tal vez le falten algunos retoques, pero mientras tanto aquí está el mío:

<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"

xmlns:moz="http://www.mozilla.org/2006/browser/search/">

<ShortName>motorGleduwiki</ShortName>

<Description>"motor de busqueda para el GleduWiki"</Description>

<InputEncoding>"UTF-8"</InputEncoding>

<Image width="16" height="16">IIIIIIIIIIIIIIIIIIII</Image>

<Url type="text/html" method="POST" template="http://wiki.gleducar.org.ar/wiki/Especial:Search">

<Param name="search" value="{searchTerms}"/>

<Param name="fulltext" value="Buscar"/>

</Url>

<Url type="application/x-suggestions+json" template="suggestionURL"/>

<moz:SearchForm>searchFormURL</moz:SearchForm>

</OpenSearchDescription>

motor.xml

Dónde IIIIIIIIIIIIIIIIIIII debe reemplazarse por la salida obtenida en http://software.hixie.ch/utilities/cgi/data/data luego de subir una imagen de 16px de lado.

Por último usé:

<script type="text/javascript">

window.external.AddSearchProvider(urlEngine);

</script>

dónde urlEngine es la url absoluta al archivo xml generado, encerrado entre comillas.


Fin de semana Pythonico

Es la noche del domingo del fin de semana en el que se llevó a cabo la 2ª Jornada Python en Santa Fe. La verdad es que tenía muchas cosas que quería contar aquí al respecto, pero también es mucho el sueño que tengo y las cosas que tengo que hacer mañana así que solamente voy a dejarles un fuerte GRACIAS, a los asistentes, disertantes, spónsores, colaboradore y al resto de los organizadores.

En la semana voy a ir dejando en formato-comentario algunas cosas/ideas/recursos sobre el evento.



Un fin de semana resfriado

Este post iba a estar titulado "Nos vemos el lunes", por que venía a mi pueblo por el fin de semana largo. Lamentablemente estuve resfriado todo el fin de semana y tuve que usarlo para cuidarme.

El resfriío se cura solo en 7 días y con el médico en una semana.

Luego de esta reseña de saber popular, los dejo! Empieza Ver para leer.


2da Jornada Python en Santa Fe

El 9 de junio se realizará en el Auditorio de la Facultad Regional Santa Fe de la Universidad Tecnológica Nacional, Argentina, la 2da Jornada Python en Santa Fe. Con el objetivo de promocionar el lenguaje Python, este año se han programado un mayor número de temas dirigidos a la comunidad de programadores, profesionales de sistemas, estudiantes y público en general. Las charlas se desarrollarán entre las 8.30 y las 18.30 y estarán a cargo de varios disertantes invitados.

El LUGLi, Grupo de Usuarios de Software Libre del Litoral, y la Universidad Tecnológica Nacional, FRSF, tienen el agrado de invitarlo a participar. La entrada es libre y gratuita.

Puede obtenerse más información y registrarse para participar del evento en http://www.pythonsantafe.com.ar


Los animales de Ubuntu

Ojo! No! Por supuesto que no estoy hablando de los desarrolladores o algo por el estilo! Me refiero a los nombres con los que llaman a sus distribuciones.

Hace unos días, con la salida de Feisty Fawn (7.04), se me ocurrió salir a la caza de los significados de los nombres de estas distribuciones. Diversas ocupaciones no me permitieron emprender el safari, pero por suerte Facundo Batista lo hizo en su blog.



Clausuras en Python

Hace unos días leí este post en el blog de Javier Smaldone.

Closures: Essentially a closure is a block of code that can be passed as an argument to a function call.

Como parte de la didáctica Javier iba mostrando ejemplos que resolvía con algún lenguaje sin Clausuras (como Java o PHP) y con Ruby (el post trata sobre las Clausuras como una fortaleza de Ruby). Mientras leía fuí resolviendo los mismos ejemplos en Python y los dejé en forma de comentos. Como la identación no salió muy bien, los reproduzco aca:

Juanjo:

Las que siguen son soluciones en Python de los ejemplos que planteaste, algunas usan clausuras, otros puede que no :)

El ejemplo simple:

Supongamos que deseamos escribir una función que tome como parámetro un arreglo de valores enteros y retorne otro arreglo, producto de multiplicar por 2 cada uno de los elementos del parámetro.
def f(a):

    return [2*x for x in a]

El ejemplo de people:

Supongamos ahora que tenemos una clase "Person", cuyo método "age" calcula la edad de la persona. Si tenemos una colección de personas en el arreglo "people" y deseamos obtener sólo aquellas que son mayores de 18 años.
[p.name for p in people if p.age > 18]

Problema 1:

Convertir las cadenas de un arreglo a mayúsculas.
a = [x.upper() for x in a]

Problema 2:

Dado un arreglo de la forma [["nombre", "apellido"]], obtener un arreglo de la forma ["apellido, nombre"]. Por ejemplo, dado:
[["Javier","Smaldone"],["Santiago","Lobos"],["Bon","Scott"]]
obtener:
["Smaldone, Javier", "Lobos, Santiago", "Scott, Bon"]
[”, “.join([y,x]) for [x,y] in a]

Problema 3:

Listar los nombres de las personas mayores de edad y mostrar la edad promedio de las mismas (según el ejemplo planteado anteriormente).

Este no quedó tan bien como los otros, pero te dejo mi interacción en REPL de Python:

>>> p1 = Persona()

>>> p1.age = 19

>>> p1.name = “Juan Hewr”

>>> p2 = Persona()

>>> p2.age = 2

>>> p2.name = “Baby Jones”

>>> p3 = Persona()

>>> p3.age = 30

>>> p3.name = “Sussan Ahoria”

>>> people = [p1, p2, p3]



>>> s = 0.0

>>> adults = [p for p in people if p.age > 18]

>>> for p in adults:

print p.name

s += p.age

Juan Hewr

Sussan Ahoria

>>> print s/len(adults)

24.5

Problema 4:

Dado un arreglo de cadenas, obtener la de mayor longitud.
max(cadenas)

Javier:

Muchas gracias Juanjo por las soluciones.

Con respecto al problema 4, un detalle:

En Ruby también puedes obtener el máximo elemento de un arreglo ‘a’ usando

a.max

Sin embargo, la idea era mostrar como aplicar una función al estilo del ‘fold’ de los lenguajes funcionales. ¿Podrías reescribir la solución en esos términos?

Juanjo:

Primero una aclaración de algo que me pasé por alto: max(a) en Python cuando a es una lista de strings no da el string más largo sino el que está más al final en un ordenamiento creciente alfabético estando las minúsculas después que las mayúsculas. Es así también en ruby?


>>> max(”hola”, “juanjo”)

‘juanjo’

>>> max(”hola”, “Juanjo”)

‘hola’

>>> max(”a”, “A”)

‘a’

>>> max(”a”, “AAAAAAAAAAAAAAAAAAAAAa”)

‘a’

>>> max(”a”, “AAAAAAAAAAAAAAAAAAAAA”, “a”)

‘a’

>>> max(”AAAAAAAAAAAAAAAAAAAAA”, “a”)

‘a’

>>> max(”b”, “a”)

‘b’

>>> max(”B”, “a”)

‘a’

Javier:

Así es, Juanjo. Yo también me equivoqué. max, aplicado a strings devuelve el máximo según el orden lexicográfico, y no según la longitud.

Me sigue quedando la duda. ¿Hay algo similar a ‘inject’ o ‘fold’ en Python?

Juanjo:

Ahora si vamos a intentar resolver el ejemplo 4 en Python:

Mmm inject está bueno para resolver ese problema.. pero creo que no tenemos algo así en Python. Intentemos de todas formas:

Tenemos una lista de strings:

a = [”hola”, “juAnjO”, “Argentina”, “8″]

Una función ‘criterio’:

def longer(a, b):

    if len(a) > len(b):

        return a

    else:

        return b

And this magic functions called ‘mas’:

def mas(l, c, v):

    if l:

        return mas(l[1:], c, c(l[0], v))

    else:

        return v

Que nos va a permitir hacer algo como esto:

>>> mas(a, longer, “”)

‘Argentina’

Mirando desde más cerca.. esta función ‘mas’, es muy parecida a ‘inject’, salvo por el nombre :)

>>> inject = mas

>>> numeros = [1,2,3,4,5,6]

>>> def suma(a, b):

    return a + b

>>> inject(numeros, suma, 0)

21

Mmm parece que funciona, comprobemoslo:

>>> sum(numeros)

21

Si!

Nos leemos!


Smarter N-Puzzle

N-Puzzle sigue sin tener una real inteligencia, pero hice una modificación que lo hace verse un poco más inteligente:

Si un jugador o el desordenador aleatorio hace movimientos que se cancelan entre sí

    <li>Izquierda - Derecha</li>
    
    <li>Izquierda - Izquierda - Derecha - Derecha</li>
    
    <li>Izquierda - Izquierda - Arriba - Arriba - Derecha - Izquierda - Abajo - Abajo - Derecha - Derecha</li>
    

    el siguiente algoritmo es capás de eliminarlos de la lista de acciones y así lograr una resolución en menos movimientos y que parezca menos tonta.

    El método que encapsula al algoritmo en cuestión es llamado cada vez que se entra al modo Auto Solve:

    
        def _reduce_actions(self):
    
            '''This method try to reduce the actions' log
    
            removing repeted moves.'''
    
    
    
            log = self.actions_log
    
            stack = []
    
    
    
            while log:
    
    
    
                a = log.pop()
    
                ia = self._inverse_action(a)
    
    
    
                if stack:
    
                    s = stack.pop()
    
                    if ia != s:
    
                        stack += [s, a]
    
                else:
    
                    stack += [a]
    
    
    
                print "Stack: ", len(stack)
    
                print "Log: ", len(log)
    
    
    
            stack.reverse()
    
            self.actions_log = stack

    Download last version: n-puzzle-0.1-2