Garbanzos en Perl, Python y C

Hola,

Hoy vengo con una entrada un tanto peculiar. El otro día hablando de una boda, me comentaron que iban a hacer una especie de broma para el regalo de los novios.

La broma consistía en no darles el dinero que les habían preparado como regalo hasta que superasen la siguiente prueba:

Los novios recibirían 22 botes de garbanzos numerados del 1 al 22. Dentro de ellos, cada garbanzo tendría escrito un carácter pero sólo uno en cada bote podría tener un dígito. No habría ningún dígito de valor 0. Habría dos botes sin dígito, que serían descartados por los novios al darse cuenta de esto.

Habría que tomar esos botes en orden ascendente y conseguir el garbanzo con el dígito de cada uno de ellos. De esta forma, los dígitos, en el orden indicado en el bote, formarían un número de 20 cifras que se correspondería con el número de la cuenta donde estaría guardado el dinero del regalo.

Al conseguir el número se llevarían el regalo.

El tema es que para que no fuera tan complicado de entender sin indicaciones se les dieron unas directrices a los novios. Hablando sobre ellas, se me ocurrió que podía programar un pequeño script que hiciera el trabajo sucio y eso es lo que vengo a presentaros hoy. He hecho el mismo script en varios lenguajes de programación: C, Python y Perl.

En todos ellos considero que cada bote es un argumento de entrada (considero que se introducen en orden) y que los garbanzos son del tipo Char (son caracteres al fin y al cabo). La salida del comando sería la pantalla.

El primero es el de C. El más complejo de todos, al menos para mí. En el resto el número final podría ser más largo que 20 caracteres pero en C no porque lo cargo estáticamente. No se gestiona si te pasas de largo así que… cuidado.

#include<stdio.h>
#include<string.h>

int main(int argc, char * argv[]){
    int i;
    char numero_final[20];
    int pos_final=0; //para iterar por el número final
    // Itero por los botes
    for( i=0; i<argc; i++ ){
        // Itero por los garbanzos
        int j;
        int num_garbanzos = strlen(argv[i]);
        for ( j=0; j<num_garbanzos; j++ ){
            char garbanzo = argv[i][j];
            // Si el garbanzo está entre 0 y 9, guardarlo
            if( garbanzo <= '9' && garbanzo >= '0'){
                numero_final[pos_final]=garbanzo;
                pos_final++;
                // Hemos terminado con este bote
                break;
            }
        }
    }
    numero_final[pos_final]='\0';
    printf("%s\n",numero_final);
    return 1;
}

Como veis, es necesario usar índices para iterar por los arrays. Además se evalúan los caracteres uno a uno y los strings se tratan como un array de caracteres (lo que son en realidad vaya). Además, necesitamos incluir un par de librerías para hacer una cosa así de simple.

El siguiente es el código en Python. No sé si será la forma más pythonic de hacerlo, pero bueno. En este caso ya no necesitamos índices para iterar (de hecho sería más difícil hacerlo con ellos que sin ellos) y ya no declaramos las variables (por ejemplo garbanzo). Tenemos que importar sys para tratar los argumentos de entrada. En este caso podría tener muchos más botes y el programa funcionaría.

import sys
botes = sys.argv
num_cuenta = ""
for bote in botes:
    for garbanzo in bote:
        if garbanzo in "123456789":
            num_cuenta += garbanzo
            break
print num_cuenta

Para terminar Perl. Tampoco sé si es la forma más canónica de hacer esto en Perl, pero así es como lo he hecho yo. En perl sólo tenemos una iteración porque la otra la realizamos con una expresión regular (en los otros también se podría, pero Perl es el amo de esto). No necesitamos importar nada y, probablemente, el programa sea el menos legible de todos.

my @botes=@ARGV;
my $bote;
my $final_num;
foreach $bote (@botes){
    my $number;
    ($number) = $bote =~ /(\d)/smg;
    $final_num .= $number;
}           
print $final_num;

¿Es eso todo?

Pues no!

He comprobado los tiempos usando la herramienta time para que veáis lo que tarda cada programa en ejecutarse. He metido los mismos argumentos (caracteres aleatorios).

Python tarda un poco más. Me sorprende gratamente lo rápido que es Perl. Y C… ya sabemos cómo es C.

Aquí tenéis C, compilado con nombre a.out:

ekaitz@DaComputah:~/Documents/Garbanzos$ time ./a.out ahofhasbfao spojhla9asafa asfa8asfasfgabadg a7dafgagagfs a7safasfaas 6aaaaa aasfasfa7a  afasga6 6a 5a 5a 4a s4s 4asas 3asfa 3asf a2saf 3asfa 3asf
987767665544433233

real    0m0.002s
user    0m0.000s
sys     0m0.000s

Ahora Python:

ekaitz@DaComputah:~/Documents/Garbanzos$ time python garbanzos.py ahofhasbfao spojhla9asafa asfa8asfasfgabadg a7dafgagagfs a7safasfaas 6aaaaa aasfasfa7a  afasga6 6a 5a 5a 4a s4s 4asas 3asfa 3asf a2saf 3asfa 3asf
987767665544433233

real    0m0.020s
user    0m0.012s
sys     0m0.004s

Y Perl:

ekaitz@DaComputah:~/Documents/Garbanzos$ time perl garbanzos.pl ahofhasbfao spojhla9asafa asfa8asfasfgabadg a7dafgagagfs a7safasfaas 6aaaaa aasfasfa7a  afasga6 6a 5a 5a 4a s4s 4asas 3asfa 3asf a2saf 3asfa 3asf 
987767665544433233
real    0m0.004s
user    0m0.000s
sys     0m0.000s

Ahora sí que es todo. Espero que os haya parecido interesante.

¡Saludos!

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s