Las matemáticas recreativas siempre presentan posibles retos para la programación. En esta ocasión hablaremos de los curiosos números de Munchhausen y plantearemos el reto a solucionar.
Dice la Wikipedia: "un número de Munchhausen (o Münchhausen) es un número natural n el cual la suma de sus dígitos (en base 10), elevados a la misma potencia de ellos mismos es el mismo número es decir n. Por ejemplo:
El término fue una invención del ingeniero y matemático holandés, Daan van Berkel, que en el 2009 estudió este tipo de números. La idea de llamarlos así a estos números se debe a que cada dígito está "elevado" por sí mismo y esto evoca la historia de Barón Munchhausen que se elevó a sí mismo hacia arriba jalando su propia coleta. Como todos sabemos, el Barón de Munchhausen era un mentiroso crónico e inventaba las más increíbles historias, recopiladas en un libro incluso.
La idea de estos números puede dar a un nuevo reto lúdico. Se trata de averiguar cuántos números hay con esta propiedad. El 1, por ejemplo, cumple pues es 1^1 = 1. El segundo número es el 3435 y parece que no hay más. Consideramos normalmente que 0^0 = 1, pero si tomamos la definición "no estándar" de que 0^0 = 0, entonces el número 438,579,088 es también de Munchhausen.
El reto lúdico es pues escribir un programa que dado un intervalo de números naturales, empezando en 1 y terminando en el número que se deseé, el programa encuentre en el menor tiempo posible cuáles son los números de Munchhausen. Aunque ya sabemos la respuesta, el ganador del reto será quien encuentre en el menor tiempo posible el resultado correcto, considerando un intervalo de al menos 10 millones de números: del 1 al 10 millones. Además, el programa deberá usar la definición estándar de 0^0 = 1 y 0^0 = 0, esto, desde luego, por separado.
Cabe señalar que yo ya escribí mi propia versión del reto. En este caso, le puse una opción que me dice qué número está procesando, pero para efectos de mediciones, le puedo quitar eso porque el despliegue de esta información hace mucho más lenta la ejecución del software.
El reto tendrá como premio una taza de la Morsa. Si el ganador es de provincia, se le mandará un USB de 8 GB al menos, porque mandar una taza por mensajería es ridículamente costoso. 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. El ganador cede su código fuente a la comunidad. Es decir, se promueve el código abierto.
Las respuestas al reto deben mandarlas a morsa@la-morsa.com. A quien le interese ver mi programa corriendo, envíeme un mensaje a mi correo y le mandaré el enlace para que lo descarguen y vean mis resultados. ¡Suerte!
Tengo un buen amigo amante de todos los productos Apple. Y aunque en ocasiones llega al fanatismo, no es de aquellos que se forma en una fila de la tienda Apple más cercana y espera días ahí para comprarse el nuevo teléfono que incluso aún no ha sido lanzado oficialmente. Mi amigo es un diseñador gráfico talentoso y ha usado Apple desde hace muchos años. Vamos, para decirlo brevemente, es un usuario educado. Por alguna razón, ahora se compró un teléfono con sistema operativo Android. Me dejo a manera de reto el entender para qué, alguien como él, compraría un teléfono con ese sistema operativo, cuando está tan feliz fon su iPhone, iPad y sus iCosas.
Comentamos todo esto por Facebook y dijo: "Compré un LG Optimus. [...] Nadie en la casa lo quiso ni tocar, después de verlo por un minuto. Se ve de entrada chafón, como hecho al aventón, sin seguir lineamientos. Los iconos están revueltos, no se distinguen unos de otros, las letras son poco legibles... y puedo seguir un buen rato". Contesté diciéndole que me aburrían sus juicios tan sesgados y poco después añadí "Es que lo pones como inusable prácticamente, y no es así. Millones usan teléfonos Android sin problemas". Mi amigo respondió entonces: "No es inusable, pero no es elegante e intuitivo. Simplemente 'barato', como las cosas chinas".
¿Intuitivo? Eso me brincó. ¿Quién dijo que el uso de un teléfono es intuitivo? ¿Qué quiere decir alguien cuando indica que su programa, su aplicación, su dispositivo, es intuitivo? Dudo que un aparato de la modernidad pueda considerarse intuitivo. Veamos lo que indica la Wikipedia: "Se describe como el conocimiento que es directo e inmediato, sin intervención de la deducción o del razonamiento, siendo considerado como evidente". ¿Evidente? Pensemos por ejemplo en el ratón de las computadoras. ¿Es su uso intuitivo? Les apuesto que no. Pongan a alguien que nunca ha usado una computadora con un ratón y notarán que no le alcanza la mesa, se le acaba. No sabe cómo usarlo. ¿Dónde está lo intuitivo en eso? ¿Y qué decir de los ratones con dos botones? ¿Es su uso intuitivo? ¿Se entiende sin intervención de la deducción o del razonamiento para qué sirven? Apuesto que no. El dispositivo del ratón tiene una serie de acciones que se pueden hacer con éste, pero claramente están definidas bajo el contexto de las aplicaciones y el sistema operativo. Podemos, pues, marcar un texto y copiarlo con Ctrl-C para después pegarlo en alguna otra aplicación con Ctrl-V. Eso no es intuitivo de ninguna manera. Nadie de la nada me saldrá con que sabe de forma intuitiva para qué sirven semejantes comandos.
Y en esos momentos recuerdo una plática a la que fui hace muchos años, en donde estaban mostrando las bondades del procesador de palabras más famoso de ese momento. Cabe recordar que no había interfaces gráficas, todo era en modo texto, en MS-DOS. El conferenciante explicaba los diversos comandos, que se hacían con combinaciones de teclas. De pronto dijo: "Para imprimir usamos Ctrl-P"... Y alguien lo interrumpió y le preguntó: "¿No debería ser Ctrl-I, de Imprimir?". Y en lugar de aclarar que el comando Ctrl-I era para insertar texto, el conferenciante dijo: "No, se decidió usar Ctrl-P porque es imPrimir, donde la fuerza de la palabra recae en la P, precisamente". Respuesta que si la pensamos, es una tontería. Se usaba Ctrl-P porque en inglés imprimir es Print. Así de sencillo.
Y si vamos a otros dispositivos, pensemos en el iPad o en cualquier tablet, veremos que los comandos gestuales no son intuitivos. No, para nada. hay que saber cómo hacer más grande el tamaño de lo que la pantalla despliega o ver cómo hacemos para crear carpetas, o borrar iconos de la pantalla que ya no nos sirven, etcétera. Nada de eso es intuitivo. Que se aprenda rápidamente es otra cosa. Lo que me queda claro es que no existe interfaces intuitivas si estas no funcionan como lo hacen los objetos cotidianos en la casa. De hecho, la intuición en el uso de algo no creo que exista en la mayoría de los casos, más bien se aprende desde pequeño. Por ejemplo, sabemos que si presionamos el interruptor de una lámpara, ésta se enciende (o se apaga). Pero eso no es un conocimiento que nace sin intervención de la deducción o del razonamiento. No, es algo que vemos tan cotidianamente que ni siquiera lo pensamos. Quizás si hablamos de intuición, podemos pensar que un niño intuitivamente toma el pezón de su madre cuando va a ser amamantado. Con eso se concluye, no es producto de deducción o de razonamiento. Eso sí es intuitivo.
Y podemos dar más ejemplos. Pongamos un automóvil estándar (no automático). Aprender a manejar este tipo de vehículos requiere práctica. No hay intuición en esto. Hay que aprender a escuchar el motor para hacer los cambios de velocidades, por ejemplo,. Pero si pasan unos años y nos compramos otro automóvil, que quizás tiene más velocidades (o menos), podremos salir de la agencia manejándolo sin problemas. ¿Eso es parte de la intuición? ¿El vendedor nos habría dicho que su manejo es intuitivo? Probablemente si lo hizo nos mintió. No, es algo que hemos aprendido antes y que ya lo hemos grabado en el subconsciente, por lo cual el manejar un automóvil parece que se hace casi sin pensar.
En resumen, no veo lo intuitivo en aplicaciones, en programas o en dispositivos. Eso es simplemente un argumento de la mercadotecnia que nos hemos creído sin siquiera analizarlo. Y como ilustración de lo que la mercadotecnia logra, vean esta parodia de IKEA. Creo que habla más de esto por sí misma.
Prolog es uno de los lenguajes más fascinantes que hayan sido creados. Basado en el paradigma de la programación lógica, en donde el programador describe el problema y Prolog, a través de su algoritmo de resolución y unificación, llamado algoritmo de Roberts, resuelve la dificultad planteada.
A diferencia de los lenguajes tradicionales de cuarta generación como Pascal o C, Prolog pide al programador definir las condiciones iniciales y de frontera, así como las rutinas que describen lo que queremos que el programa haga para hallar una solución. En términos generales, Prolog es una especie de "case" gigantesco, como el de los lenguajes más comunes, con la diferencia de que siempre actúa igual, siguiendo un orden determinado de acuerdo a la posición física de las cláusulas en el programa.
Además, Prolog hace énfasis en la recursión, lo cual hace que los programas sean por demás elegantes. Ya lo decía Niklaus Wirth (el inventor de Pascal): "iteratum humanum est, recursivitum divinum est", lo cual es algo así como "iterar es de humano, hacer recursión es de dioses".
Pues bien, hoy en mi clase de Programación Lógica y Funcional les dije a mis alumnos que resolveríamos un problema típico: el de pasar una cifra numérica a su equivalente en texto. Así, si el sistema recibe 2345 deberá dar como resultado "dos mil trescientos cuarenta y cinco". Este tipo de transformaciones hay que hacerlas comúnmente cuando escribimos, por ejemplo, un cheque.
Pues bien, me senté a escribir el programa en cuestión, que había bosquejado en la clase y en el que me comprometí a diseñar y mostrarles en la siguiente clase, que será el próximo miércoles. He aquí el código en turbo Prolog 2.0:
/********************************************/
/* Programa que traduce de números a letras */
/* Versión 1.0 */
/* 16 mayo 2011 */
/* Programó: La Morsa */
/********************************************/
pasa_num_a_letras(Cifra) :- Cifra div 1000 <> 0, /* la cifra tiene miles */
Miles = Cifra div 1000,
equiv(Miles,Resultado),
write(Resultado, " mil "),
Cientos = Cifra - (Miles * 1000),
pasa_num_a_letras(Cientos).
pasa_num_a_letras(Cifra) :-
Cifra div 100 <> 0, /* la cifra tiene cientos */
Cien = Cifra div 100,
Cien1 = Cien * 100,
equiv(Cien1,Resultado),
write(Resultado," "),
Decenas = Cifra - (Cien * 100),
pasa_num_a_letras(Decenas).
pasa_num_a_letras(Cifra) :- /* unidades entre 11 y 20 */
Cifra > 9,
Cifra < 21, equiv(Cifra,Resultado), write(Resultado," pesos").
pasa_num_a_letras(Cifra) :- Cifra div 10 <> 0, /* la cifra tiene decenas */
Dec = Cifra div 10,
Dec1 = Dec * 10,
equiv(Dec1,Resultado),
write(Resultado," y "),
Unidades = Cifra - (Dec * 10), pasa_num_a_letras(Unidades).