Productividad aleatoria ponderada en Python

Este artículo, que he clasificado en las categorías “Productividad” y “Python” es peculiar porque mata dos pájaros de un tiro: puede resultar útil tanto al lector interesado en lograr un mayor rendimiento como al estudiante de Python. Se explica una técnica de productividad y a continuación se muestra cómo automatizarla utilizando el lenguaje de programación Python.

En Productividad aleatoria describí un método al que recurro con frecuencia para estimular mi rendimiento al enfrentarme a un conjunto de tareas pendientes de índole diversa.

La esencia del método consiste en dejar que sea el azar el que decida cuál será la siguiente tarea a ejecutar. Esto supone los siguientes beneficios:

Evita perder tiempo decidiendo nuestra siguiente ocupación. ¿Eres capaz de evaluar cuánto tiempo malgastas mareando la perdiz a lo largo del día, decidiendo qué hacer? Calcúlalo y quizás te lleves una sorpresa.

– Dota de un componente lúdico a nuestro sistema de productividad, haciéndolo más divertido y motivante. Es un juego que se rige con reglas sencillas: la suerte está echada y nuestra misión consiste en ejecutar la tarea con eficacia y eficiencia, sin rechistar ni cuestionar si otra labor nos resulta más apetecible.

– Todas las tareas, las que nos gustan más y las que no tanto, están incluidas en el bombo de la fortuna. A menudo solemos postergar las menos atractivas, que probablemente son las más importantes, de modo que no encontramos nunca tiempo para hacerlas. El azar no entiende de preferencias personales y poco a poco irás liquidando todas esas tareas ingratas pero necesarias.

En el artículo sugerí un método sencillo para la gestión aleatoria de tareas que sólo precisaba de dos herramientas: un editor de texto plano y un generador de números aleatorios. Recordémoslo con algo más de detalle.

Como editor de texto sirve cualquiera que incluya numeración de líneas, como Notepad++ o gedit, entre muchísimos otros. Para la elección de un número al azar puedes utilizar el widget de random.org que figura en la esquina inferior izquierda de esta página.

La forma de operar es sencilla: una tarea en cada línea del fichero y que el generador de números aleatorios decida cúal elegimos entre el total de líneas existentes.

Por eso me he referido a un editor de texto plano en lugar de un procesador de textos. En un editor de texto plano no hay cambio de línea lógica hasta que no se pulsa ENTER. Aunque el programa divida la línea lógica en más líneas físicas, en el caso de que no quepa entera en el ancho de la ventana, el número de línea sigue siendo el mismo.

Obsérvalo en el siguiente ejemplo:

Las líneas 3 y 6 no caben enteras en el ancho de la ventana establecido, pero el número de línea se mantiene el mismo.

Una vez tenemos el listado de tareas candidatas sólo resta elegir una al azar. En nuestro ejemplo, habría que elegir un número entre 1 y 9:

Localizamos la línea 8 en el fichero y esa será nuestra próxima tarea a realizar: “Revisión y actualización de un artículo del blog con más de un año de antigüedad”.

Podemos refinar el método introduciendo la gestión de prioridades. Sería deseable que las tareas más importantes, aquellas que nos hacen avanzar hacia nuestros principales objetivos, tuviesen más “papeletas” en el sorteo que las que menos contribuyen. Para lograr esto basta con repetir la tarea en la lista las veces que consideremos necesarias, aumentando así su peso específico y la probabilidad de que resulten elegidas.

Para ahorrar tiempo, en vez de repetir la tarea, agregaremos líneas en blanco debajo de ella (como cuando usamos pares de comillas bajo de un texto para indicar que es una repetición exacta de él). Basta con tener presente que una línea en blanco hace mención a la tarea encima de ella.

Obsérvalo en el ejemplo:

Hemos dejado un espacio en blanco después de la tarea 3 y dos después de la 8. Esto es lo mismo que si hubiéramos repetido la tarea en esos huecos, pero se tarda menos con una simple pulsación de ENTER. De este modo, estamos indicando que las tareas 3 y 8 tienen un peso específico de 2 y 3, respectivamente; es decir, la tarea 3 tiene dos veces más probabilidades de salir elegida que cualquier otra ordinaria, y la 8 tres veces más.

Si ahora la elección de la linea al azar recayera en una línea en blanco, como la 4, la tarea elegida sería la inmediatamente superior que estuviera ocupada, es decir, la 3: “Preparar un solo para Joe Ibuprofeno y transcribirlo en solfeo y tablatura con Guitar Pro”.

Si no estás interesado en la programación en Python, puedes abandonar ya la lectura del artículo, pues lo que resta de él está dedicado a la creación de un pequeño programa que seleccione, entre todas las tareas definidas y ponderadas en el fichero tareas.txt, una al azar.

Nuestra labor será dotar de contenido al fichero, que el programa se ocupará de la elección automáticamente.

Mostraremos algunas técnicas nuevas no presentadas aún en el blog, como:

– Apertura un fichero de texto que emplea una codificación diferente a la del nativa del sistema operativo sobre el que corre el intérprete Python.

– Recuperación de una línea concreta de un fichero de texto.

– Comprobación de si una línea está en blanco o no.

Para la función aleatoria, necesitaremos importar el módulo random, en el que está definida la función randint(), que emplearemos para la elección de un número entero al azar.

import random

Lo primero que realiza el programa es recuperar todas las líneas del fichero de tareas y almacenarlas en una lista:

fichero = open('tareas.txt', encoding = 'utf-8')
tareas = fichero.readlines()
fichero.close()

La primera línea abre el fichero tareas.txt en modo texto y lectura, opciones por omisión cuando no se especifica nada más. Pero fíjate en la novedad, el parámetro encoding = 'utf-8'.

Python, cuando abre un fichero de texto, necesita saber cómo está codificado para poder interpretarlo correctamente. Si no decimos nada en la función open(), Python, por defecto, asume que está codificado en el modo nativo propio del sistema operativo en el que está corriendo el intérprete. Yo suelo emplear utf-8, una de las maneras de codificar caracteres Unicode, pero Python no tiene forma de saber que mi fichero está empleando ese formato salvo que se lo diga expresamente. El parámetro extra que hemos empleado en open() se ocupa de notificárselo.

Vemos en acción, a continuación, el método readlines() que, como sabemos, rellena una lista en la que cada elemento es una línea del fichero.

Esta es una técnica sencilla que debe figurar en tu repertorio para procesar ficheros de texto:

1) Abre el fichero en modo lectura.
2) Carga su contenido en una lista.
3) Cierra el fichero.
4) Procesa la lista con el contenido del fichero.
5) Abre el fichero en modo escritura (destruyendo el anterior).
6) Vuelca la lista procesada al fichero con el método writelines().
7) Cierra el fichero.

En este ejemplo no serán necesarios los tres pasos últimos, pues no vamos a modificar el fichero. Más adelante contruiremos otros programas sencillos que requerirán las siete etapas.

Una advertencia importante: esta técnica no es más que eso, una técnica. Existen otras formas de trabajar con ficheros de texto, como veremos, que serán más adecuadas que esta en determinadas ocasiones. La presentada aquí tiene una limitación: todo el contenido del fichero se vuelca en memoria. Si la memoria de la que dispone Python es inferior al tamaño del fichero el programa no funcionará.

No uses este método para ficheros muy grandes. En estos casos es preferible que la recuperación del archivo se realice en bloques controlados, liberando la memoria cada vez que se cargue un nuevo bloque tras su proceso.

Cerramos el fichero tan pronto hemos terminado con él. No necesitaremos acceder nuevamente a él.

Para elegir un número de línea al azar, primero debemos saber cuántas líneas hay. Como cada elemento de la lista contiene una única línea, el total de elementos será el total de líneas:

len(tareas)

Hay que elegir una de ellas: la primera en la lista tiene por índice cero, por lo que la última tendrá por índice el total de elementos de la lista menos 1:

len(tareas) - 1

Para elegir un entero al azar entre cero y len(tareas) – 1, usamos la función randint() indicando esos extremos como parámetros:

random.randint(0, len(tareas) - 1)

Recuperamos, entonces, el elemento de la lista que tiene ese índice elegido al azar:

tarea_aleatoria = tareas[random.randint(0, len(tareas) - 1)]

Esa sería la línea buscada, si no fuera porque podría suceder que se tratara de una línea en blanco. En ese caso, habría que buscar la inmediatamente superior que no lo esté.

Pero, ¿qué caracteriza una línea en blanco?

El único contenido que tiene una línea en blanco es el cambio de línea \n. Con esto, el siguiente bucle while comprueba que la línea no esté en blanco y, si lo está, trata de recuperar el elemento anterior hasta que encuentre una línea que no lo esté:

while tarea_aleatoria == '\n':
    tarea_aleatoria = tareas[random.randint(0, len(tareas) - 1) - 1]

Una vez localizada, la imprimimos y misión cumplida:

print(tarea_aleatoria)

Te dejo el código completo del programa:

# Productividad aleatoria ponderada

import random

fichero = open('tareas.txt', encoding = 'utf-8')
tareas = fichero.readlines()
fichero.close()

tarea_aleatoria = tareas[random.randint(0, len(tareas) - 1)]

while tarea_aleatoria == '\n':
    tarea_aleatoria = tareas[random.randint(0, len(tareas) - 1) - 1]

print(tarea_aleatoria)

Javier Montero Gabarró


http://elclubdelautodidacta.es/wp/2012/11/productividad-aleatoria-ponderada-en-python/


El texto de este artículo se encuentra sometido a una licencia Creative Commons del tipo CC-BY-NC-ND (reconocimiento, no comercial, sin obra derivada, 3.0 unported)


El Club del Autodidacta


Índice completo de los artículos de la categoría Productividad.


Consulta el índice completo de artículos relacionados con Python.

10 opiniones en “Productividad aleatoria ponderada en Python”

  1. import random
    with open(‘tareas.txt’) as f:
    print(random.choice(filter(bool, f.readlines())))

    – fichero pequeño en tamaño
    – una tarea por línea

    * filter(bool, lines) descarta las líneas en las que bool(“cadena”) evalúa a falso, es decir, las vacías.

    🙂

  2. Método alternativo:

    – Material: libreta, bolígrafos de colores, dado de 6 caras.

    – Procedimiento:
    1. Según surjan tareas anótalas en la libreta. Clasifícalas por colores según su importancia.
    2. Tira el dado y mira qué tarea te ha tocado realizar
    3. Cuando la termines, táchala y tira de nuevo.

    Consejo: las tareas muy largas deben ser dividas para facilitar el estímulo cerebral y no cansarse.

  3. Aquí va otro método que suelo usar (copiando y pegando la lista de tareas en una consola con Python abierto):
    tareas = “””Tarea1
    Tarea2
    Tarea3″””.split(‘\n’)
    random.choice(tareas)

    Quizás no sea la forma mas elegante ni la mejor de hacerlo pero a mi me funciona.
    Opcionalmente, y para aumentar la aleatoriedad, se puede cambiar random.choice(tareas) por lo siguiente:
    azar = random.Random(44568346908467435)
    azar.choice(tareas)
    Cabe destacar que al objeto Random se lo puede inicializar con cualquier cosa y no se limita solo a números.

Deja un comentario