Showing posts with label reto. Show all posts
Showing posts with label reto. Show all posts

Saturday, August 23, 2014

Nuevo reto ¿de la programación lúdica?


Hace un par de sábados, en una de las reuniones de ajedrez que suelo tener ese día, estaba un palindromista famoso, Willy de Winter, Maestro Internacional de Ajedrez (ver foto más abajo), traductor perito y un especialista en idiomas (al menos cuatro y me quedo corto). En esa misma reunión de pronto apareció Merlina Acevedo, que ha sido en twitter todo un fenómeno por sus complejísimos palíndromas, por la longitud de los mismos, que rayan en la locura.


Ya aquí hablamos de Merlina y de los palíndromas en general, pero en esa reunión a la que hago referencia, le pregunté a Merlina si había palíndromas hechos con palabras y no letras. Vamos, que en los palíndromas normales, la unidad es la letra y por ello por ejemplo, "Sé verlas al revés"  (así podría definirse con un palíndroma al palíndroma), se lee igual de principio a fin y viceversa, pero ¿y si la unidad de estos palíndromas es la palabra?, por ejemplo: "Nuevamente comamos, bebamos, comamos nuevamente". Esto no es un palíndroma en donde se lee de derecho al reves en letras pero si la unidad no es la letra, sino la palabra, entonces estaríamos hablando de un "palíndroma de palabras" (no sé cómo  bautizarlo).

 Merlina me dijo que pensaba que si existían, tenían estos "seudo-palíndromas" ser palíndromas por sí mismos, por ejemplo: "somos seres somos", pero le puse un ejemplo: "político pinche, pinche político", y no se cumple esta condición que ella suponía que era obligatoria. Un par de días después, Merlina me mandó uno que halló, en inglés: "Blessed are they that believe that they are blessed" (que más o menos se traduce como esto: "Bendecidos son aquellos que se creen bendecidos" (que en español pierde la propiedad de ser palíndromas por palabras)... Después me mandó un mensaje que decía: "Afortunados no los que somos, ¿somos qué los no afortunados?", pero no convence. Y lo modificó de esta manera: "Afortunados no somos, somos no afortunados" y acto seguido en un nuevo mensaje me puso éste: "Afortunados no somos muchos, muchos somos no afortunados". Da la impresión que estos palíndromas hechos con palabras y no con letras son mucho más difíciles de hacer o peor aún, parece ser muy complejo expresar ideas tan sofisticadas como la propia Merlina ha hecho con los palíndromas originales en donde la unidad es la letra.


Merlina Acevedo, con su libro de palíndromas y aforismos


Así pues, en un intento de entender más este problema, el siguiente reto de la programacióbn lúdica no involucra a los programadores necesariamente, sino a todos aquellos que quizás tengan en ingenio para crear palíndromas con palabras y no con letras. Al mejor palíndroma de palabras que se me mande se ganará una taza con el logo de La Morsa, una gorra y un cuaderno de notas, donativo de Qualcomm más quizás un par de premios más de otros amigos que están colaborando en esta idea. Pueden mandarme sus palíndromas con palabras a morsa@la-morsa.com. El reto durará un par de semanas. Cabe decir que si no hay buenos palíndromas, el concurso quedará desierto, es decir, no se dará premio alguno, cosa que espero no pase.

Si el ganador es de provincia o fuera de este país, le mandaré una memoria USB de al menos 8 GB. Esto es porque el costo de enviar una taza es ridículamente costoso. Así que por quizás única ocasión, este reto de la programación lúdica no tiene que ver con programación de computadoras, sino con algo más sutil, el ingenio para crear palíndromas de palabras. Esperemos que así le entre más gente a los retos propuestos.

Saturday, June 21, 2014

Programación lúdica: La escondida riqueza del juego del gato


Todos jugamos alguna vez al gato. Hallamos pronto que no era un juego difícil de dominar. Vamos, incluso probablemente dedujimos que después de la primera jugada en el centro, si el rival no tira en las esquinas pierde irremediablemente. Uno olvida rápidamente este tipo de juegos, pues no representa ningún reto. Pero en realidad, sí puede serlo. Por ejemplo, a los alumnos en los primeros años de las carreras que tienen que ver con programación, bien puede ser una tarea a programar. Ahí coinciden algunas ideas interesantes, por ejemplo, la valoración de las posiciones a partir del algoritmo minimax, el cual se usa incluso en la valoración de las posiciones de ajedrez.

Hace unos días estaba yo en el trafico capitalino, atorado a la altura de Polanco, y pensaba en la inmortalidad del cangrejo y en cuántas posibles posiciones se pueden tener en el juego del gato, es decir, ¿cuántas posiciones del gato se pueden dar desde la primera jugada hasta que el juego termina? Pensaba que en realidad requiero conocer la cuarta parte de todas las configuraciones (o posiciones posibles), pues finalmente el gato tiene una simetría de la cual se puede sacar ventaja.

Asi pues, lanzo el siguiente reto a los lectores/programadores: Hágase un programa que genere todas las posibles configuraciones del gato, desde el inicio hasta el final. Guárdese cada posición en un archivo de texto. Por ejemplo, quien escriba un programa de esta naturaleza debería entregarme un texto aproximadamente como éste:

bbb
bxb
bbb

obb
bxb
bbb

obb
bxb
xbb
 
en donde "b" es una casilla vacía. Desde luego, las otras dos letras son "o" y "x".

Se piden solamente las configuraciones o posiciones legales. No se valen cosas como ésta:

xxx
bbb
bbb
por ejemplo.

¿El premio? Una taza con el logotipo de la Morsa a la mejor solución. Esto solamente aplica a los programadores que vivan en el DF (mandar a provincia o a otros países una taza es estúpidamente costoso). En caso de que los concursantes sean de otros países o de la provincia mexicana, el premio será una memoria USB de al menos 16 GBytes. Y sí, sé que no son los grandes premios pero mientras no tengamos patrocinadores, esto es lo que hay.

Evidentemente quien gane será anunciado en unocero y hasta tendrá sus quince minutos de fama.

Cabe señalar que este concurso busca simplemente alentar el trabajo de la programación y mostrar que puede ser lúdica. Es un concurso de buena fe. Si hay, por ejemplo, dos o más respuestas satisfactorias, ganará quien la haya mandado primero. Así que "en sus marcas, listos, ¡fuego!"

Wednesday, March 20, 2013

Nuevo reto de programación lúdica: Óleo digital



Una característica de las imágenes en la computadora es que son digitales, es decir, hechas de dígitos, de números, pues. Cada dígito representa un punto en la pantalla, y normalmente el valor que vemos corresponde al color que ese punto tiene en la imagen. De esta manera, las fotografías digitales (ya sean escaneadas o tomadas con alguna cámara digital), son en realidad una matriz cuadrada de pixeles (puntos en la pantalla), que bien puede ser en color o en blanco y negro.

En la medida en que la tecnología ha progresado, hemos pasado de imágenes de 256 colores a las que nos pueden mostrar alrededor 16 millones de colores. Actualmente, cualquier tarjeta de video que se precie de serlo muestra los tres componentes de color R(ed – rojo), G(reen – verde) y B(lue – azul) en cada pixel (o punto), el cual puede ser un valor entre 0 y 255. De esta manera, 256 x 256 x 256 nos da 16,777,216 posibles colores. Cabe señalar que el ojo humano no puede ver semejante espectro de colores, pero es un hecho que la computadora puede desplegarlos.

Ahora bien, cada fotografía digital es en realidad una aproximación sobre lo que se fotografía tomando una cámara analógica, es decir, una que tenga filme. Por ello mismo, “el grano” de la cámara digital es la precisión con la cual puede distinguir los detalles. Por ello vemos que hay cámaras digitales de 4, 8, 10 o más megapixeles. De hecho, tampoco ya el ojo humano no distingue entre, digamos, 8 y 10 megapixeles. De esta manera, la resolución de las imágenes ha crecido y con ello la necesidad de usar cada vez más bytes en los archivos y memorias donde se guarda.

Con el advenimiento de la tecnología digital de imágenes y su gran aceptación en el mercado, estamos viendo desaparecer las cámaras analógicas y los filmes. Se acabó el revelado y los costos asociados a esto. Además, con la generación de imágenes digitales, también nació la posibilidad de post procesarlas para generar efectos en ellas. Photoshop, por ejemplo, es uno de los programas más populares para manipulación digital de imágenes.

Filtros Digitales


La manipulación de una imagen digital se denomina genéricamente como un “filtro”, el cual convierte una imagen en alguna otra cosa. Existen filtros que son reversibles, mientras que también los hay aquellos que no lo son. De acuerdo a las necesidades, se pueden tener diversos filtros o transformaciones que pueden aplicarse a una imagen incluso ya filtrada. Los resultados suelen ser sorprendentes.

Muchos filtros gráficos, sino es que todos, se consideran transformaciones gráficas basadas en una matriz llamada también “convolución” (no se asuste por la palabra, es sólo un término que da precisión a todo esto). Estas convoluciones es el procesar segmentos de la imagen a partir de una submatriz (que puede ser de 3×3, 4×4, 5×5, etc.) de pixeles, que va recorriendo la imagen completa. El resultado final convierte la imagen original en alguna otra cosa. Existen filtros para reconocer bordes, para quitar ruido, para meter ruido, para hacer más precisa una imagen, para hacerla más borrosa, para deformarla, etc. Las aplicaciones son infinitas.

El filtro Oleo Digital (en tonos de grises)


En el libro Beyond Photography (The Digital Darkroom), de Gerard J. Holzmann, que trabajó algunos años en los Laboratorios Bell, el autor nos habla de cómo alterar imágenes. Ahí presenta la fotografía de Dennis Ritchie (uno de los inventores del lenguaje C), y al procesarla la convierte en la misma imagen, pero como si fuese pintada al óleo. De acuerdo al autor, lo que hace es esto: “Para cada punto en la imagen, un programa calcula el histograma de los 36 bordes del derredor [del punto de interés], en la vecindad del punto de interés, y se asigna el valor [al propio punto que estamos procesando] el valor que contenga la mayor frecuencia. El resultado es casi una pintura al óleo”.

Cuando intenté escribir mi propio programa que hiciese este filtro “al óleo”, decidí, sin embargo, no usar 36 puntos, sino 49, para que así mi matriz (llamada: de convolución), mi cuadrícula, tenga un punto central en [4,4]. Con una convolución par no se puede tener un punto central. Igualmente, generé un arreglo de 256 números (de 0 a 255), para colocar la frecuencia de los 49 valores de la matriz de 7×7, que voy recorriendo en la imagen, pixel a pixel. Así, saco los primeros 49 valores y encuentro la frecuencia de los mismos. En el punto de interés pongo el que tenga la mayor frecuencia. ¿Qué pasa si hay más de uno valor con la mayor frecuencia? ¿Cuál pongo? Cualquiera de ellos. Da lo mismo.


La imagen de la izquierda es la de Dennis Ritchie (el creador del lenguaje C), como aparece en el libro de Holzmann. A la derecha aparece mi propia versión del algoritmo descrito. ¿Cuál le gusta más a usted? Este programa funcionaba originalmente sólo con imágenes en blanco y negro (tonos de grises), pues en imágenes de tonos de gris hay nada más 256 tonos y además, las componentes RGB de cada pixel tienen el mismo valor, es decir, R=B=G, lo cual hace sencillo el encontrar el histograma de frecuencias de color. La diferencia en resultados es que Holzmann usa una matriz par y yo uso matrices impares.

El filtro Oleo Digital (en color)

Para poder generar imágenes al mejor estilo óleo, en color, se necesita hacer una modificación que parece trivial, pero que no lo es. La dificultad es que al querer pasar a color, tenemos que las imágenes pueden contener poco más de 16 millones de colores. Esto, obviamente hace el problema un poco más difícil, pues no podemos generar un arreglo de 16 millones (para seguir con la técnica usada en la parte en tonos de gris), pues es totalmente ineficiente y absurdo. Así, aquí hay que contar y crear el histograma de frecuencias de manera más sencilla. Después de dos semanas de darle la vuelta al problema, finalmente hallé una solución simple. La implementé y de pronto ya tenía mi programa que generaba el óleo digital en color. (¿Cómo le hice?… es parte del reto)

Al poder hacer el histograma y hallar cuál es el valor de mayor frecuencia, simplemente lo pinto para cada punto en la pantalla. Es claro que el filtro hace una imagen que pierde precisión contra una fotografía real, pero se asemeja, sin duda, a un cuadro hecho al óleo.

El reto es pues el siguiente: hágase el filtro óleo en color siguiendo la técnica: “Para cada punto en la imagen, un programa calcula el histograma de los 36 bordes del derredor [del punto de interés] y se asigna el valor [al propio punto de interés] el valor que contenga la mayor frecuencia. El resultado es casi una pintura al óleo”.




He aquí las bases adicionales del reto:

  • Ganará el programa que transforme la imagen de Lena (que aparece más abajo), en el menor tiempo posible. El segundo mejor tiempo obtendrá el segundo lugar.
  • Habrá dos lugares: Ambos se llevarán una taza con el logotipo de La_Morsa. Mi intención es que al imprimir esas tazas aparezca una leyenda con el título de la misma y el lugar obtenido, para que quede constancia por el tiempo de vida de la taza.
  • Los programas pueden hacerse en cualquier lenguaje de propósito general y no se vale usar en éste particularmente, bibliotecas que hagan filtros gráficos. Los programadores tienen que resolver el problema por sí mismo, sin ayuda de bibliotecas externas. (Desde luego, se vale usar alguna biblioteca para cargar/guardar la imagen de Lena para procesarla, la cual es un JPG, pero nada más). Así pues, C, C++, C#, Pascal (Delphi), Javascript, Python, Ruby, Visual BASIC, Visual C, Java, etcétera, son idóneos para esta labor.
  • Los autores de los programas deberán mandar el código fuente y el archivo ejecutable en Windows 7.
  • Un autor puede mandar versiones mejoradas de su propio software dentro del tiempo del concurso. No se tomarán en cuenta las que se salgan del tiempo establecido.
  • En la medida de lo posible, el programa debe indicar el tiempo total del proceso realizado para crear la imagen al óleo de Lena.
  • El autor debe enviar el código fuente y quienes ganen aceptan que su código quede accesible para quien lo quiera ver.
  • Los programas deben poderse ejecutar en el sistema operativo Windows 7 de 64 bits. Se correrán en una máquina AMD con 6 núcleos y los resultados obtenidos son inapelables y definitivos. De nuevo aclaro: este es un reto de buena fe y no un concurso estrictamente. Los premios son meramente un estímulo extra para que se animen a entrarle al reto. Evidentemente asumo que el código de cada concursante es creación del mismo y que no andan copiando el código de otras partes, foros, sitios en Internet, etcétera. En caso de hallar que el código fue copiado, el programador queda descalificado.
  • El reto dura una semana a partir del día de la publicación del artículo. Por ejemplo, si éste se publica un 10 de mayo a las 3 de la tarde, el reto se cierra el 17 de mayo a esa misma hora.
  • Cuando reciba algún programa participante en el reto, le enviaré un acuse de recibo para asegurarnos que están todos los que son y son todos los que están.
  • El concurso es para quienes viven en la República Mexicana. Si alguien de otro país quiere participar es bienvenido, pero no podrá acceder a los premios.
  • Los programas deben ser enviados a morsa@la-morsa.com o en su defecto a lopem@hotmail.com, por si alguna de las direcciones no funciona.

Así que queridos y entusiastas programadores, a entrarle al reto. Afilen sus herramientas de programación y que gane el mejor.

Imagen a procesar (512 x 512 pixeles):


Friday, March 15, 2013

Eficiencia en cómputo y resultados del reto Collatz


Actualmente tenemos programas que hacen un sinfín de tareas. Muchos de ellos -sino es que la mayoría- usan una interfaz gráfica para que los usuarios puedan tomar decisiones a través de botones, listas de opciones, etcétera. La interfaz gráfica se impuso por su facilidad de uso y el modo texto, o consola, fue desapareciendo poco a poco. Y aunque aún existe en los sistemas de cómputo, ya prácticamente todos los sistemas operativos utiliza una interfaz gráficaz, que se monta al arrancar el sistema y que ya está fusionado con la parte de interacción gráfica.

Pero ¿qué tanto influye la interfaz gráfica en el desempeño de un equipo de cómputo? ¿Cuántos recursos más requiere para correr un programa con relativa velocidad? Es una pregunta interesante y que a veces nos olvidamos de ello pues es claro que ahora las máquinas corren a unos 3 GHz y tienen 2, 4, 8 o más Gbytes de memoria. De hecho, cuando había computadoras de 8 bits y algunos intentos rudimentarios de interfaz gráfica (como el MousePaint de Apple //e), era claro que las limitaciones del hardware eran demasiadas.

Gracias a los avances en este rubro, parece que podemos tener una hermosa interfaz gráfica con el usuario y un desempeño fenomenal, pero aunque lo parezca, no es así. Hace unos días convoqué, vía este medio, a un reto de programación. Se trataba de hallar la secuencia más larga de números de Collatz. Hubo bastante aceptación de este "concurso" y he recibido una veintena de programas.

El reto en particular era hallar la secuencia más larga en un número del 1 al millón. Originalmente tomé mi código para calcular la secuencia de Collatz de un número y lo puse en forma de ciclo para que calculara todas las secuencias de 1 al millón. Como el programa trabajaba con una biblioteca para manejar números extremadamente grandes (más de 1000 cifras), el programa -al ejecutarse- tardaba más de diez minutos. Mi software desplegaba toda la secuencia para cada número y esto, evidentemente lo hacía muy lento.

Como en el reto sólo se pide hallar la secuencia más larga, no hay necesidad de desplegar cada cálculo que la máquina hace. Así, quitando el despliegue de esta información, el programa tardaba la mitad, es decir, unos 5 minutos. Aún así era lento. Vi programas de algunos de los participantes que tardaban menos de 15 segundos. ¿Cómo hacer para que mi programa corriera más rápido? Quité entonces la biblioteca de números grandes y usé el tipo predefinido LongInt. El programa, sin embargo, se atoraba en el número 999216. Vi la referencia y hallé que los LongInt aceptan números entre -2147483648 y 2147483647. Como algo estaba pasando, cambié las definiciones de los números a usar a LongWord, que aceptan valores entre 0 y 4294967295 y entonces mi programa corrió. Tardaba ahora alrededor de un minuto para hallar la secuencia pedida.

Pero ¿se podía ir más allá? La solución era hacer un programa que corriera sin necesidad del "overhead" que le mete la interfaz gráfica. Delphi permite crear aplicaciones que corran en modo consola/terminal. Se quita pues la sobrecarga que le impone la interfaz gráfica a todos los programas. Escribir código para aplicaciones sin interfaz gráfica es equivalente a escribir código en TurboPascal realmente. Con esto en mente, pasé mi programa más rápido a uno que no usara la interfaz gráfica. Así entonces, el programa no muestra los cálculos que hace. Sólo informa el resultado final. ¿Tiempo para hallar la secuencia más larga de Collatz? ¡Menos de 1 segundo! Sorprendente.

Desde luego que estos resultados pueden variar de acuerdo a la computadora que se esté usando, pero en esencia se mantiene la misma relación de velocidades. En conclusión, es claro que la interfaz gráfica hace muy lento, demasiado lento, el procesamiento de información. No pensaba que fuese tan grande esta sobrecarga, pero los números así lo indican. He aquí mi código en Delphi 7 (ejecutable disponible pidiéndomelo a mi correo morsa@la-morsa.com):

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

var
  MaxNum    : LongInt; // núm máximo
  Contador  : Integer;
  Numero    : LongWord; //núm con la secuencia más larga
  Num1      : LongWord;
  NuevoLong : LongWord;
  NuevoCont : integer;

// Números de Collatz: Encontrar la máxima secuencia usando
// LongInt en lugar de la biblioteca de números grandes
// el programa se escribió en modo consola para evitarse el
// overhead que le mete la interfaz gráfica

procedure Calcula;
begin
  write('dame número máximo a calcular ');
  Readln(Num1); //leo el máximo número a calcular
  MaxNum := Num1;
  NuevoLong := 0;
  Contador := 0;
  NuevoCont := 0;
  repeat
    repeat
      if Num1 mod 2 = 0 then Num1 := Num1 div 2
                        else Num1 := (Num1 * 3) + 1;
      inc(Contador);
    until Num1 = 1;
    if Contador > NuevoCont then
    begin
      NuevoLong := MaxNum;
      NuevoCont := Contador;
    end;
    Contador := 0;
    dec(MaxNum);
    Num1 := MaxNum;
  Until MaxNum = 1;
  Writeln('Número: '+inttostr(NuevoLong)+ ' iteraciones: ' + inttostr(NuevoCont));
  readln;
end;

begin //main
  Calcula
end.


  Cabe señalar que hubo diferentes lenguajes en uso: Delphi, C++, C#, Ruby, Javascript, Java y Python. A pesar de ser interpretados algunos de estos lenguajes, su desempeño es estupendo, aunque me parece, no pueden competir con el compilador que genere código nativo y que además tiene, muchas veces, directivas para optimización. En este reto en particular, la velocidad para hallar la solución era el factor ganador. Sin embargo, en cualquier caso, es interesante ver el desempeño de varios de los lenguajes en boga. Una vez dicho esto, van los resultados del reto de la secuencia más larga en los números de Collatz, de 1 a un millón:  

  • Juan Claudio Toledo 00.029 segundos (primer lugar)  
  • Nayely Riverón Domínguez 00.047 segundos (segundo lugar) 
  • José Raúl Escobedo Arreola 00.053 segundos 
  • Darío Alvarez Aranda 00.164 segundos 
  • Fabían Vargas Quijano (*) 00.200 segundos
  • Carlos Torres Almonte 00.310 segundos 
  • Kevin Reyes 00.320 segundos  
  • Manuel López Michelone 00.420 segundos (fuera de concurso) 
  • Luis Alfredo Juárez Blanco 00.640 segundos 
  • Carlos Morales 00.699 segundos 
  • Cyb3rxPuNk . 01.010 segundos 
  • Eleazar Prieto 01.130 segundos 
  • Ricardo Padilla Amezcua 02.324 segundos 
  • Gerardo Robledo 03.300 segundos 
  • Luis Rivera 05.638 segundos 
  • Rafael Mendoza 06.540 segundos 
  • Francisco Pérez 06.790 segundos 
  • lugo tache 07.320 segundos 
  • Eduardo Ruíz 07.490 segundos 
  • David Garza 09.000 segundos 
  • Ernesto Valderrama Blum 36.070 segundos 
  • Roberto López Bedolla 36.350 segundos 
  • Gabriel Romero 41.200 segundos 
  • Rockodev 110.720 segundos 
  • Juan Rafael Corrales más de 5 minutos 
  • Cristian Castro Cienfuegos N/A (**)  
(*) Vargas Quijano incluyó en el envío de su programa, un estudio sobre una forma de optimizar el problema para que busque de manera más inteligente. Muy interesante enfoque, sin duda.

(**) Nunca pude correr su programa. Mi sistema decía que faltaba un archivo dll que busqué, descargué y puse en mi sistema, pero jamás lo reconoció o algo extraño pasó.

Juan Claudio Toledo, ganador del reto de Collatz

Me dice Juan Claudio Toledo, que está terminando su doctorado en la UNAM, (el ganador de este reto), en el correo en donde me mandó el programa, los siguiente:  

Me di cuenta que la respuesta al problema debe ser siempre > N/2. Es decir, el entero entre 1 y N con mayor ciclo debe estar en la segunda mitad del intervalo [1,N]. ¿Por qué? Acá lo demuestro, por reducción al absurdo.  

Sea x el entero entre 1 y N con mayor ciclo. Supongamos que x <= N/2. Puedo definir y = 2*x; como x <= N/2, tenemos que y <= N, por lo que y es también un candidato. Pero como y es par, la primera iteración del algoritmo empezando en y nos daría y/2 = x, y llegamos a x. De ahí la secuencia iría igual que si se empezara en x. Debido a esto, el ciclo de y es un paso más largo que el de x. Entonces x no es el entero de mayor ciclo, y se llega a una contradicción. Por lo tanto, x debe ser mayor que N/2.  

Modifiqué el programa para que buscara a partir de N/2+1, pero me salió un tiempo más grande. La razón: estoy usando un cache para recordar los valores ya calculados, pero en este caso nunca se calculan los ciclos de números menores que N/2. Y pues esos valores se usan bastante. Empezando desde cualquier número, la secuencia debe pasar *al menos* log_2(N/2)~18 veces por números en la primera mitad. De forma que al hacer este cambio, aunque calculo sólo la mitad de los casos, me cuesta más pues no aprovecho tanto el cache.

Así entonces, como podrán ver, esta conjetura de Collatz tiene mucha tela de donde cortar. Con respecto al reto me gustaría hacer algunas aclaraciones:
  • Los tiempos los medí en mi computadora, con un procesador AMD de seis núcleos y sistema operativo Windows 7 de 64 bits. Puede haber máquinas en donde los concursantes probaron y sus programas corrieron más rápido que lo que mi máquina reporta. Los tiempos para el reto se miden desde mi máquina.
  • El fallo es inapelable. Este es un concurso hecho de buena fe, tanto por quienes participan en él como yo, quien evalúa los resultados de la manera más legal y justa posible. Aún así y para que no quede duda: los resultados son inapelables y definitivos.
  • Los premios tienen como objetivo motivar a quienes quieren concursar, pero desde luego, solamente es una motivación extra. Lo importante aquí es mostrarse como un programador que puede ser mejor que los demás en eficiencia, en maneras de resolver un problema de programación.
  • Cuando quise probar algunos de los programas hubo errores. Por ejemplo, no hacían correctamente el cálculo. En su momento les indiqué a los concursantes con estas dificultades sobre los problemas de su software y les pedí que me mandaran las versiones corregidas. Quienes por alguna razón no me las mandaron, simplemente quedaron fuera del reto.
  • Sobre los ganadores: El primer lugar, tiene derecho a elegir el premio: la taza con el logo de La_Morsa o la tarjeta SD de 4 GB. Me pondré en contacto por correo electrónico con los ganadores para darles su premio y que me den una foto para ponerlos en la galería virtual de honor. Felicidades. La verdad me satisface mucho ver que hay tanto empuje y tan buenos programadores en este país. Me tiene muy contento eso. Agradezco la entusiasta participación y prepárense para el siguiente reto.
Los programas ganadores (el código fuente), son los siguientes:

Programa de Juan Claudio Toledo:

/************************************************************\
* collatz.cpp                                                *
*                                                            *
* Autor: Juan C. Toledo                                      *
* Fecha: 13 de marzo de 2013                                 *
*                                                            *
* Encuentra el entero entre 1 y N con el ciclo mas largo,    *
* bajo el algoritmo de la conjetura de Collatz. Emplea       *
* memoization para optimizar la busqueda.                    *
*                                                            *
* Copyright 2013 Juan C. Toledo                              *
*                                                            *
* Este archivo es parte de collatz.                          *
*                                                            *
* collatz es software libre: usted puede redistribuirlo y/o  *
* modificarlo bajo los términos de la GNU General Public     *
* License, publicada por la Free Software Foundation, ya sea *
* la versión 3 de la licencia, o (a su opción) cualquier     *
* versión posterior.                                         *
*                                                            *
* collatz se distribuye con la esperanza de que sea útil,    *
* pero sin ninguna garantía; ni siquiera la garantía         *
* implícita de comerciabilidad o idoneidad para un propósito *
* PARTICULAR. Consulte la GNU General Public License para    *
* más detalles.                                              *
*                                                            *
* Usted debe haber recibido una copia de la GNU General      *
* Public License junto con Foobar.                           *
* Si no, véase http://www.gnu.org/licenses/                  *
\************************************************************/

#include < stdio .h >;

int main () {

  // ======================
  // Configuracion
  // fijar verbose a false para mejorar el tiempo de ejecucion
  
  const int N = 1000000;
  bool verbose = false; 

  // ======================

  int ciclos[N+1];
  int i, pasos, maxpasos, maxnum;
  long int x;

  // Calculamos para todos los enteros desde 1 hasta N
  maxpasos = 0;
  maxnum = 0;
  for (i=1; i<=N; i++) {

    // Bucle que simula el juego
    x = i;
    pasos = 0;
    while (x!=1){
      // Si x es menor a i, ya hemos calculado su ciclo
      if (xmaxpasos) {
      maxpasos = pasos;
      maxnum = i;
      if (verbose) printf(" Nuevo record!");
    }
    if (verbose) printf("\n"); 
  }

  printf("Ciclo mas largo (n<=%i): ",N);
  printf("%i con %i pasos\n",maxnum,maxpasos);
  
  return 0;
}

Nayely Riverón Domínguez, segundo lugar en el reto de Coillatz

El código de Nayely:
    
#include < stdio .h >;
    #include < stdlib .h >;
    #include < time .h >;

    int main(void){
         unsigned long tope=1000000, iteraciones=0, i=0, num=0, iteracion_mayor=0, numero_mayor=0;
         int *iteraciones_totales;
         
         printf("Ingrese tope: ");
         scanf("%lu",&tope);

         clock_t t_ini, t_fin;
         double secs;
         t_ini = clock();
         
         size_t tamanyo=tope;
         iteraciones_totales = (int *)malloc( tamanyo*sizeof(int) );
         
         for(i=1;i<=tope;i++){  
            iteraciones=0;            
            num=i;
            while (num > 1) {
                    if(numiteracion_mayor){
                     iteracion_mayor=iteraciones;
                     numero_mayor=i;
            }
            
         }
         
         printf("DEL 1 AL %lu\n\nNumero: %lu\nIteraciones: %lu\n\n",tope,numero_mayor,iteracion_mayor);
         
         t_fin = clock();
         secs = (double)(t_fin - t_ini) / CLOCKS_PER_SEC;
         printf("El tiempo de calculo fue: %.16g milisegundos\n", secs * 1000.0);

         
         getche();
         free(iteraciones_totales);    
         
         return 0;
    }