Concepto:Si no tienes ni idea de qué va el título, tranquilo. Tampoco lo tenía yo, pero en esta vida se aprende algo todos los días. Hace unos días, leyendo la tira cómica de una página que me suele gustar me encontré con esto:
(http://imgs.xkcd.com/comics/collatz_conjecture.png)
La verdad es que, aunque las clases de mates eran mortalmente aburridas, siempre me han intrigado los puzles matemáticos y este es bastante curioso. Se trata de la conjetura Collatz, llamado así por Lothar Collatz, matemático alemán quien al parecer fue el primero en postular la conjetura, aunque la misma lleva varios nombres más (Ulam, Kakutani, Thwaies, Hasse, Syracuse...). Finalmente se le conoce por el nombre más genérico:
3n+1Para los que prefieren fórmulas:
(http://upload.wikimedia.org/math/0/6/5/065cac984cf6f6f07fd55a27ba19ba54.png)
La conjetura es la siguiente: comienza con cualquier numero natural (un entero positivo). Si el número es par se divide entre dos, si es impar se multiplica por tres y se añade uno. Repite el proceso ad infinitum. Independientemente del número que elijas, finalmente llegarás a 1.
Aunque hasta ahora se ha demostrado por fuerza bruta que la conjetura es correcta en todos los números naturales hasta 20 × 2
58 no se ha demostrado que sea cierta.
Aplicación:Pasemos a la práctica. MINDSTORMS no solo es una plataforma excelente para robots sino también para aprender algo de programación (indispensable para la creación de robots) y esta es mi primera incursión en este campo.
Cuando ya tenía una idea general de cómo quería implementar esta conjetura en un programa (no tanto por el cálculo en sí, sino más bien por la interfaz de usuario que lo acompaña) me dio por mirar si alguien ya había tenido l misma feliz idea en NXTLOG (http://mindstorms.lego.com/NXTLOG/default.aspx). ¡Craso error! Brian Davis hizo un programa llamado Hailstones (otro de los múltiples nombres de esta conjetura) que es una maravilla de sencillez de uso y contenido en bloques muy aprovechables. Por un momento estuve tentado de abandonar, pero decidí modificar mi interfaz de entrada y aprovechar algunas de las excelentes ideas que se encuentran en ese programa: MyBlocks tan útiles como "Modulo" o un bloque que te permite escribir un número con su correspondiente etiqueta en una línea determinada o llenar la pantalla de texto con un solo bloque.
Otra excelente idea es el bloque GetKey que monitoriza cual de los botones del NXT es pulsado y da como resultado un número que se puede usar para hacer que se ejecute una determinada acción.
Como el programa de Brian Davis depende enteramente del teclado – y llegué a encontrarlo algo engorroso para meter el número inicial – decidí usar un motor como método de entrada, en combinación con los botones para añadir dígitos (de más a menos, es decir si tengo un 1 y añado un 9 el resultado es 19), restarlos (dar un paso atrás y volverá quitar ese 9, dejando solo 1) o aceptar el valor para el cálculo.
(http://www.hispalug.com/galeria/albums/userpics/10361/Collatz-1.jpg)
El cálculo se puede hacer de dos maneras: automático y paso a paso. El modo paso a paso permite ver cada iteración del cálculo y muestra el resultado hasta ese momento y el número de pasos ejecutados.
Este puede ser un buen momento para dar un ejemplo de esos pasos. Supongamos que empecemos por un numero bajo: 5. La secuencia que se desarrolla es la siguiente
5 – 16 – 8 -4 – 2 – 1 un total de 5 iteraciones
Para 7 la secuencia es:
7 – 22 – 11 - 34 – 17 – 52 – 26 – 13 – 40 – 20 – 10 – 5 – 16 – 8 – 4 – 2 – 1 un total de 16 iteraciones, parte de las cuales coinciden con las de 5
En el NXT queda de la siguiente manera: después de seleccionar el número se puede elegir hacer proceso paso a paso (botón derecho), automático (botón izquierdo), o salir (botón central)
(http://www.hispalug.com/galeria/albums/userpics/10361/Collatz-2.jpg)
Haciéndolo de manera manual se pueden ver los pasos intermedios y en cualquier caso el resultado final:
(http://www.hispalug.com/galeria/albums/userpics/10361/Collatz-3.jpg)(http://www.hispalug.com/galeria/albums/userpics/10361/Collatz-4.jpg)
Algunas ideas de programación:Como se puede ver en la fórmula que aparece más arriba, una manera de saber si un número es par o impar es calcular el módulo de la división entre 2. Yo tampoco soy de mates, pero en programación el módulo es la parte del número que no se puede dividir si usar fracciones: así el módulo de 4/3 es 1.
Aquí nos podemos aprovechar del hecho de que NXT-G 1 solo funciona con números enteros... no sabe de decimales. NXT-G 2.0 sí usa coma flotante por lo que en un principio no se podría hacer lo mismo, pero... es posible instalar de manera sencilla los 'antiguos' bloques' de números enteros en NXT-G 2.0!
Usando estos bloques se puede obtener el módulo de la siguiente manera:
(http://www.hispalug.com/galeria/albums/userpics/10361/modulo.png)
Primero divido un número entre 2 (en la fórmula más arriba hablábamos del módulo de 2) y el resultado se multiplica por 2. Si el número fue par la división es "limpia" y el resultado de la multiplicación será el mismo. La diferencia entre el número original y el resultado de la multiplicación será 0.
Si el número es impar, la división generará un resto que se pierda al no poder procesarlo el bloque de matemáticas 'integras' y la comparación arrojará un saldo positivo. De este modo se sabe si hay que aplicar n/2 o 3n+1 al número.
¿Cómo instalar esos bloques? Es muy sencillo, pero no lo voy a poner aquí X)
He empezado a hacer una compilación de bloques adicionales para NXT-G (http://lrobotikas.net/wiki/index.php?title=Bloques_adicionales_para_NXT-G) en la wiki de LRoboticas. En el apartado "Datos" hay una entrada para los "Bloques con números enteros (http://lrobotikas.net/wiki/index.php?title=Bloques_con_n%C3%BAmeros_enteros)"
donde explico cómo hacer precisamente esto.
Me ha recordado cuando hacía mis pinitos con la programación de mi hp48GX, tanto en User-RPL como en Sys-RPL (los dos lenguajes más extendidos en el mundillo "jacapaca"). Y muy curiosa la conjetura del Sr. Collatz, no la conocía (en este foro se aprende de todo, diga lo que diga el ministro Gabilondo :D :D :D).
A ver si los chicos MINDSTORMS se atreven con el último teorema de Fermat que se demostró hace bien poco ;)
Mmm Cálculo Numérico :_( :_( :_(
Una bonita hipótesis Matemática traducida a Mindstorms.
Una buena forma de practicar con los comandos while e if (O su equivalente LEGO :angel:)
Efectivamente Blastem, if y más if ya que NXT-G no tiene While (el while se consigue juntando un if con un bucle).
Me he dado cuenta de que me he quedado algo corto en mi primer mensaje ya que faltan algunas cosillas. Una foto de "MOC" por ejemplo; así que para saldar la deuda:
(http://www.hispalug.com/galeria/albums/userpics/10361/CollatzMOC.jpg)
Tampoco he enseñado ninguno de los bloques creados por Brian Davis que he aprovechado para el programa. Se trata de los siguientes:
PrintNumber Permite escribir un número precedido de una leyenda o "etiqueta". De esta manera se combinan dos funciones que de otra manera habría que implementar por separado. Aprovecha la posibilidad que brinda el bloque de texto de concatenar varios fragmentos: en este caso unir una leyenda y un número previamente convertido en 'texto'.
(http://www.hispalug.com/galeria/albums/userpics/10361/PrintNumber.png)
PrintLine Para que el anterior bloque funcione hace falta este otro bloque especial. No hace más que calcular la posición en píxeles de la línea deseada (cada línea tiene una altura de 8 píxeles y la línea 8 empieza en 0 píxeles) para leugo permitir insertar texto en esa línea.
(http://www.hispalug.com/galeria/albums/userpics/10361/PrintLine.png)
Printscreen También hace uso del bloque PrintLine. Parece una tontería pero es un bloque de lo más práctico. Permite - a través del panel de configuración del bloque - escribir en una vez todo el texto que se quiere mostrar en la pantalla, en vez de tener que hacerlo línea por línea.
(http://www.hispalug.com/galeria/albums/userpics/10361/PrintScreen.png)
Manti: después de leer un poco sobre Fermat en Inet sigo igual... no veo por donde cogerlo para transformarlo en algo que se pueda hacer con un NXT, más que nada porque consistiría en demostrar que algo NO es posible: justo lo contrario de la conjetura Collatz que dice que SI es posible. Pero si tienes alguna sugerencia sobre cómo hacerlo...
Es cierto, este famoso teorema afirma que no existen números naturales que cumplan x^n + y^n = z^n. Se trata de una desigualdad, no de una igualdad.
Cita de: Jetro en 07 de Mayo de 2010, 21:27:26 PM
Pero si tienes alguna sugerencia sobre cómo hacerlo...
Sabes que mis competencias abarcan naves gigantes y montañas inmensas... ¡¡no estoy preparado!! :_( :_(
LEGO-Demostración
Bricks^n + Slopes^n=(Dimensiones Mantianas)^n :D :D :angel:
Es un Teorema feo de programar para buscar soluciones, ya que tienen que ser aproximadas numéricamente (Ya que con enteros hay más bien pocas que no sean múltiplos)
Me ha gustado mucho el sistema de entrada, seguro que lo usaré :). El problema es ideal para enseñar sentencias de flujo y además das utilidad a muchos bloques para NXT-G. Tendrías que poner la traducción para NXC o RobotC para que se vea como se simplifica el programa ;).
Esto si que si :B, enunciados pequeños problemas gigantes:
Cuadratura del círculo -> dos milenios: Teoría de grupos.
Teorema de Fermat -> 350 años: Teoría algebraica, teorema de moludaridad. Tendrían que hacer los libros con más margen.
Conjetura de Collatz -> ??? ¿Qué nos deparará? ¿Lo viviremos?
...
Muchos otros que se quedan en el tintero.
Para completar la primera fase del proyecto aún os debía el código en NXT-G
En cuento esté disponible se podrá descargar aquí: http://www.megaupload.com/?d=CX0HVXKA
He tardado un poco porque aunque el código funcionaba me estaba dando algunos problemas - no siempre compilaba bien dependiendo de si usaba NXT-G Retail o Edu y tardaba mucho en abrirse en cualquiera de los dos. He podido localizar los problemas - guardaban relación con el hecho que sacar hilos de un bloque de conmutación (if) no parece buena praxis...
Más adelante quiero ver si puedo rescribir el código para NXC, salvo que alguien se me adelante :D
Después de analizar el comportamiento de las series generadas por algunos números vi necesario añadir otra lectura al proyecto inicial: la del número máxima alcanzado.
Calculando los números del 1 al 30 sobresale el 27: tiene un tiempo de órbita (número de iteraciones necesarias para llegar a 1) de 111 (¡) y el valor máximo que alcanza es de 9232. ¿Será que las series tienen números preferidos? Hasta el 27 todo estaba más o menos controlado. ¿Será una excepción? ¿Habrá un tiempo de órbita medio para cada rango de valores?
Para poder dar respuesta a esas preguntas hará falta otro programa que recoja datos a mayor velocidad porque mirando de uno en uno ...
Dicho y hecho, el nuevo programa (se llama Collatz a secas y se puede descargar aquí: http://www.megaupload.com/?d=69810RF8).
El programa ha pasado por bastantes cambios a medida que iba consiguiendo resultados, aunque el principio sigue siendo el mismo: además de aplicar la comprobación de par/impar y la operación matemática correspondiente según el caso, el programa guarda datos en un archivo de texto en el NXT. El 'problema' de esta técnica es que NXT-G usa una nueva línea para cada dato. Sin embargo hay un sencillo truco para poder guardar datos correlacionados (número, tiempo de órbita y máximo): convertir los números en texto (el aspecto sigue siendo el mismo pero el programa lo trata de manera diferente) y concatenar esos datos, insertando comas. El archivo resultante tiene este aspecto:
1,0,1
2,1,2
3,7,16
4,2,4
5,5,16
6,8,16
7,16,52
8,3,8
9,19,52
10,6,16
Etc. etc.
Inicialmente hice un bucle con contador para calcular los primeros 1000 números, pero al ver la velocidad con la que se calculaban las series decidí hacer un bucle infinito... y parar cuando me cansara.
Dejé correr el contador hasta 10.000, pero curiosamente el archivo que obtuve se paraba bruscamente (sin siguiera terminar de escribir uno de los números) poco después de los 1.000.
Al revisar la memoria del NXT me di cuenta de que tenía unos cuantos programas en el NXT y que por eso seguramente se había truncado la creación del archivo. Borré absolutamente todo lo que se puede borrar (incluido archivos 'de sistema' al que tienes acceso desde NXT-G) y probé nuevamente:
Esta vez el resultado fue bastante mejor, pero aún así el archivo se truncaba alrededor de los 4.000. Por si acaso desfragmenté la memoria del NXT (esto se puede hacer con una opción en el programa NeXTExplorer (http://bricxcc.sourceforge.net/utilities.html)) y repetí la prueba... con idéntico resultado.
A continuación descubrí que la misma herramienta con la que puedes borra o descargar archivos del NXT (la segunda pestaña de la ventana de enlace con el NXT) permite ver en tiempo real algo de lo que pasa con la memoria del NXT. Así descubrí que cada pocos segundos se creaba un archivo con el mismo nombre que el que usaba para recoger los datos, pero terminado en .bak. Por alguna razón, de vez en cuando se crea un archivo de respaldo que posteriormente vuelve a desaparecer, pero para hacer esto en NXT necesita tener el doble de espacio libre que el tamaño del archivo final, por lo que la función se trunca al consumir la mitad del espacio disponible :(
Cabía una última optimización: obviar el número calculado de la serie: más adelante, al importar los datos en una hoja de cálculo, el número de fila puede asumir esa función así que el dato sobra. De este modo se puede recoger los datos de casi un tercio más de números con lo que he llegado a los 6.000
¿ Las conclusiones?
Para empezar el tiempo de órbita. Aunque los tiempos de órbita de números cercanos se pueden parecer también hay grandes variaciones y no hay ningún patrón evidente. Sin embargo llama la atención que ciertos valores tienen tiempos idénticos, estando uno al lado del otro. 12 y 13 o 20 y 21 o 52 y 53 tienen tiempos de órbita idénticos. Sin embargo 14 casi duplica el tiempo de órbita de 12 y 13...
(http://www.hispalug.com/galeria/albums/userpics/10361/Tiempo_de_%C3%B3rbita.jpg)
En cuanto a los valores máximos, las cosas son similares aunque un poco más estructuradas. Eliminando los valores más altos se puede observar claramente una línea de 'preferencia' en la altura de 9232 y varias líneas de números que se acoplan a múltiplos de su valor inicial (1, 1.5, 3, 4,5, 6,75...)
(http://www.hispalug.com/galeria/albums/userpics/10361/Cota_superior2.jpg)
En la segunda imagen he ajustado el eje vertical con una escala logarítmica para poder ver todos los valores generados.
(http://www.hispalug.com/galeria/albums/userpics/10361/Cota_superior.jpg)
Es curioso ver cómo, aparte de la evidente línea de 9232, hay más líneas horizontales de 'preferencia' visibles.
Si alguien quiere ver el archivo de datos generado con el NXT, lo adjunto al mensaje.
Al no ser que me contradigas, no tendría que adelantarse nadie: has investigado, subido imágenes, confeccionado el hilo, programa NXT-G, ...
Otra cosa es que no quieras/puedas dedicarle más tiempo.
Edit: No es el caso, no había visto tu último mensaje, buenisimo. :)
si en vez de matlab, se utilizara en NXT en las clases de matematicas, aprobaria mas gente, seguro :angel:
A esto le llamo yo "quedarse contento" :D
Te has marcado un análisis numérico con NXT llevando la capacidad de proceso hasta su límite y analizando los datos obtenidos. (Intersesante lo de la creación de un bak para los procesos B))
Excelente lo que has hecho :angel:
De verdad que este ladrillín nunca deja de sorprendernos B)
lo siento,por algo no me gusta lo technic,no entendi naaadaaa! :_(
Es que no es Technic, es MINDSTORMS. Curiosamente en este caso los ladrillos apenas tienen algo que ver con todo el tema y aún así es LEGO :angel:
Para hacerlo todo un poco más fácil de digerir he pensado hacer un poster. Creo que una de las cosas que faltaron en la sección Technic/MINDSTORMS de la pasada Hispabrick fueron más medios (audio)visuales (aunque hubiera sido difícil poderlos colgar en alguna parte) así que pensando ya en el futuro he hecho un poster (tamaño A3) que podría servir de apoyo para explicar el proyecto. Posiblemente aún haya que limar algunos aspectos, pero creo que es una opción muy interesante
(http://www.hispalug.com/galeria/albums/userpics/10361/Collatz.jpg) (http://www.hispalug.com/galeria/displayimage.php?album=399&pos=4)
(Si pinchas en la imagen se abre en la galería del foro.
Si vuelves a pinchar se abre a tamaño mayor)
Que gran trabajo. :D
Me parece la forma ideal de incentivar al personal a introducirse en este mundillo: Un proyecto sencillo, muy llamativo y mostrando que el NXT es un ordenador.
Además si lo presentas así, seguro que lo miran dos veces.
Uhm hace unos días que me estuve leyendo este post y me gustó mucho, sinceramente todo y que no es lego propiamentedicho va bien darle al coco de tanto en tanto, cosa que me gustaría hacer más a menudo, pero la ineptitud me rodea y tengo que resolver otro tipo de problemas como la cuadratura de un lego dentro de un paquete o la factura maldita que no lleva IVA porque mi gestor me marea.
Así que en los ratos libre cuando me acuerdo de esto intento buscarle una utilidad, es decir, un caso práctico a que aplicarlo, casi todas las cosas matemáticas suelen tener una aplicación real, pero esta parece ser que no, a parte de jugar con un NXT o un rato con el ordenador programándolo en C++, Java, PHP o en lo que sea, tal me me equivoco y alguien puede decirme para que puede servir esta conjetura... Le he dado vueltas y vueltas y no sé verlo, ya sé que me salgo del post, pero me ha intrigado un poco todo esto :D
Quiero añadir que: este "juego matemático" es una de esas cosas que no tienen una solución propuesta, por eso son conjeturas.
No se para qué servirá en la vida real, pero a mi me está sirviendo para aprender algunas cosas de programación.
Para empezar he averiguado que sí se pueden sacar hilos de un bloque de conmutación*, pero (y este es un gran pero) cada caso del conmutador tiene que sacar el mismo hilo porque de lo contrario NXT-G se vuele tarumba.
Para conseguir hacerlo hay que seguir unas sencillas normas. Para empezar hay que visualizar el bloque de conmutación en "vista plana" - esto se consigue desmarcando la casilla que hay a tal efecto en el panel de configuración del bloque. Luego se puede conectar el primero de los casos al bloque externo como se ve en la primera imagen adjunta. Cuando pasas al segundo caso verás que el cable que lleva a la variable (en este caso) se 'esconde' debajo, pero resulta que se puede conectar con ese cable justo en el borde del caso, justo allí donde se esconde.
* conmutación es el término empleado en la documentación de NXT-G educational. Sin embargo en la interfaz se denomina "bifurcación" que tampoco es un término muy afortunado porque puede contener tantos casos como requieras y no solo dos...
Por fin ya he podido completar el código en NXC. Me he visto obligado a aprender unas cuantas cosas que no había hecho antes, como el uso de archivos en el NXT, pero ha sido un proyecto interesante y muy compacto: solamente hace falta un ordenador y el NXT por lo que se puede hacer en casi cualquier lugar.
Aparte del tema de los archivos también me he topado con la importancia de elegir el tipo de variable adecuado para cada caso. Resulta que el número máximo que alcanza la serie de 447 es 39364, mientras que el valor máximo que puede albergar una variable de tipo int es 32767. Me ha llevado un rato darme cuenta de que por eso el programa se colgaba... no podía avanzar. Eligiendo long int para los valores afectados se ha solucionado ese problema (long int tiene cabida para 2.147.483.647)
Otro problema tenía que ver con el hecho de que se puede combinar texto con números, pero el resultado es texto y por tanto necesita una variable tipo string.
Bueno, bastante palabrería por hoy. Os dejo con el código. Si alguien quiere preguntar algo estoy encantado de explicar lo que he hecho y porqué lo he hecho así.
Citarint uptime, count;
int seed = 1; //initialize seed at 1
byte handle, full=0;
unsigned int result;
unsigned long size, maxValue, _seed;
task main()
{
// Create file //
size = FreeMemory(); // check available memory space and create biggest possible file
result = CreateFile("CollatzData.txt", size, handle);
if (result == LDR_FILEEXISTS)// if the file aready exists
{
result = DeleteFile("CollatzData.txt"); //delete
//size = FreeMemory(); //recheck max available space and create file
result = CreateFile("CollatzData.txt", size, handle);
} // if an unexpected error ocurs inform on screen...
else if (result != LDR_SUCCESS)
{
NumOut(0, LCD_LINE1, result);
full=1; // ...and exit
Wait(3000);
}
result = CloseFile(handle);
until (full == 1) // limited loop 1000x: for (int i=0, i<1000, i++)
{
_seed = seed; // use extra var for calculation
maxValue = seed; // set maxValue to initial seed value
// print seed to screen (with label) -> seed: "n"
string msg = FormatNum("Seed: %d", seed);
TextOut(20, LCD_LINE3, msg);
//reset uptime
uptime = 0;
// Calculate numbers //
until (_seed == 1) // loop until destination is reached (seed = 1)
{
if (_seed%2 == 0) // % represents modulo -> even
_seed = _seed/2;
else // if not even -> uneven
_seed = _seed*3+1;
uptime++; // increment uptime couner by one
if (_seed >= maxValue) // check if higher value has been reached...
maxValue = _seed; // ... and set maxValue accordingly
}
// concatenate maxValue and uptime and write to file
string fdata = StrCat(NumToStr(seed), ",", NumToStr(uptime), ",", NumToStr(maxValue));
result = OpenFileAppend("CollatzData.txt", size, handle);
result = WriteLnString(handle, fdata, count);
// if file is full, close file and exit loop
if (result != LDR_SUCCESS)
{
full = 1;
NumOut(0, LCD_LINE7, result);
}
CloseFile(handle);
seed++; // increment seed by one
}
PlayTone(440, 100);
until (ButtonPressed(BTNCENTER, true)==1);
}
Si quieres echar un vistazo en profundidad al código te recomiendo que lo hagas con BricxCC ya que al dar un color distintivo a cada tipo de elemento el código se lee mucho mejor.
:O Me parece increíble lo lejos que has llegado investigando con un tema aparentemente sin utilidad práctica.
Para mi es perfecto, ejecución, presentación, no se, ¿se puede mejorar?, poco más se puede hacer.
Como bien ha dicho Blastem, eso es "quedarse contento".
Excelente trabajo.
Heh... Ya que mencionas Ulam, puedes continuar este proyecto con el "Spiral de Ulam", que tambien dibuja "lineas" raras en el campo de los numeros naturales...
El spiral de Ulam es algo mas duro para un ordenador, y no sé si el NXT da a basto...
Exelente presentacion!
Aún me queda la conversión del primer programa a NXC, y allí quiero usar algunas de las cosas que me he encontrado mientras investigaba este programa.
Además quiero explicar algo sobre el 'debugging' que he hecho en este programa ya que el método ha sido nuevo para mi - resulta que es posible monitorizar el proceso de creación y escritura en el archivo. Es por eso que en vez de escribir
CreateFile("CollatzData.txt", size, handle);
he hecho
result = CreateFile("CollatzData.txt", size, handle);
Todos los comandos relativos a archivos devuelven códigos de error/éxito y de este modo ese código se almacena en la variable mencionada. Antes de limpiar el programa, cada una de esas líneas iba se guido de otra con el comando para escribir ese resultado en la pantalla
NumOut(0, LCD_LINE1, result)(cada una con su línea de pantalla individual) y de ese modo pude comprobar qué estaba pasando con la creación del archivo paso a paso, a pesar de la velocidad con la que se ejecuta el programa. Resulta que es muy importante cerrar el archivo en el instante que ya no lo usas y aunque parece mentira, es por eso que nada más crearlo lo cierro - de lo contrario no funciona el programa ya que NXC solamente puede manejar un número limitado de variables a la vez.
Luego con el comando OpenFileAppend se abre el archivo para (volver a) escribir en él y WriteLnString se encarga de escribir el tipo de información requerida en el archivo y añadir un 'retorno de carro' (como en las antiguas máquinas de escribir) lo que significa que añade una nueva línea para que la siguiente vez que se escriba la información vaya en esa nueva línea y no en la misma.
También he usado un tono al final del programa para que me avise de que el programa ha terminado. Lleva su tiempo llenar los casi 100k que ocupa el archivo... :D
Finalmente he añadido un comando para que el programa no termine hasta que pulse el botón naranja del NXT y así poder ver el máximo número de serie calculado. Es una tontería, pero es la primera vez que uso los botones del NXT en NXC así que otra coas más aprendida para el próximo programa
until (ButtonPressed(BTNCENTER, true)==1);Ese until es de lo más útil. Simplemente espera hasta que sea cierto lo que lleva detrás en paréntesis.
Volviendo a esos casi 100k... vendrá bien una tabla comparativa entre NXT-G y NXC. Dejando de un lado la velocidad de cálculo que en principio es la misma los datos que he regogido arrojan el siguiente balance:
| NXT-G | NXC |
Tamaño del programa en PC | 2mb rbt 487kb rbtx | 3kb |
Tamaño del programa en NXT | 3566b | 1812b |
Tamaño de archivo creado | 51200b | 104868b |
Número de secuencias calculadas | 5288 | 10463 |
Cita de: Hoexbroe en 14 de Mayo de 2010, 07:04:10 AM
"Spiral de Ulam", que tambien dibuja "lineas" raras en el campo de los numeros naturales...
Lo voy a investigar!
Cita de: Jetro en 14 de Mayo de 2010, 09:52:05 AM
Lo voy a investigar!
Perdon por estas notas OT, pero me olvidé mencionar que el Spiral de Ulam es interesante desde la perspectiva de programacion, ya que se necesita una procedura recursiva para realizarlo. Supongo que el NXT es capaz¿?
Yo creo que sí. La pregunta es si yo seré capaz X)
No, no he acabado aún xD
Resulta que en NXC para poder abrir un acrhivo hay que especificar el tamaño del mismo. Es un requisito indispensable.
En NXT-G sin embargo no pasa nada si no defines el tamaño del archivo, bueno eso de que no pasa nada... Lo que pasa es que NXT-G lo abre con un tamaño X mas bien modesto, y cuando se da cuenta de que no le entran los datos, copia los datos a un archivo temporal (o renombra el archivo existente con una nueva extensión) y abre un archivo nuevo de mayor tamaño. He ahí la razón por la que no podía conseguir un archivo de más de la mitad del espacio disponible.
Eso me hizo pensar así que hice unas pruebas y cree un archivo, especificando el tamaño inicial con un tamaño por encima de esa barrera de la mitad del espacio disponible y (... redoble de tambores...) funciona!
Así que para aprovechar todo el espacio disponible necesito saber cuanto espacio hay en el momento de lanzar el programa. NXT-G no tiene una herramienta para eso, pero si es posible crearla, y eso ha hecho hace algún tiempo Guy Ziv y el bloque "Nivel de memoria" (http://lrobotikas.net/wiki/index.php?title=Nivel_de_memoria) está disponible desde la página de bloqueas adicionales para NXT-G (http://lrobotikas.net/wiki/index.php?title=Bloques_adicionales_para_NXT-G) de la wiki de LRoboticas.
(http://lrobotikas.net/wiki/images/d/db/Memory_level.png)
El bloque se enlaza directamente con el bloque de escritura y de ese modo se consigue que el archivo que se crea tenga el máximo tamaño posible.
Evidentemente esto cabia bastante algunos de los valores indicados en la tabla anterior:
| NXT-G | NXC |
Tamaño del programa en PC | 2,40mb rbt 514kb rbtx | 3kb |
Tamaño del programa en NXT | 4430b | 1812b |
Tamaño de archivo creado | 102328b | 104868b |
Número de secuencias calculadas | 10220 | 10463 |
El tamaño del archivo compilado que produce NXT-G es más del doble que el que produce NXC y eso se refleja en el tamaño disponible para el archivo de captación de datos y por tanto en el número de ciclos que este puede contener.
Además, ahora tengo la sospecha que el programa en NXT-G es bastante más lento que el en NXC, cosa que espero comprobar en breve. Antes tendré que asegurarme de que los dos programas sean lo más similares posibles porque de lo contrario la comparación no tendría sentido.
Antes de nada, me gustaría dejar muy claro que me considero a mi mismo: A- Un analfabeto en lenguajes de programación
B- Un aficionado a las matemáticas
C- Un entusiasta de la Física Aplicada
Y dicho esto, me atrevo a la lanzar una pregunta que me corroe: ¿ Se podria con todo esto hacer un robot, tanque o cualquier engendro que dentro de un "diorama rectangular" lo colocásemos en cualquier punto (que él reconocería por coordenadas) y siempre sabria llegar por sí mismo al punto 1 (o meta)?
Si esto te parece un chorrada, por favor borra el mensaje que me da mucha verguenza!!! :E
P. D. : Desde que empece a leer este hilo mi cabeza sólo piensa en el "conjunto de Mandelbrot" X)
Pues sin entrar demasiado en la parte matemática del asunto, que no se muy bien, no veo porque no. El problema sería hacerle llegar al robot en cada coordenada el número correspondiente. Consigue hecho y la máquina de cálculos por excelencia, el microprocesador, hará el resto.
Por otro lado carbea, siendo un aficionado a las matemáticas y la física aplicada, deberías trastear algún lenguaje de programación, aunque sea algo especializado en matemáticas como mathlab, las posibilidades son muy grandes.
Un post excelente Jetro.
Saludos
Cita de: carbea en 14 de Mayo de 2010, 23:51:56 PM
Y dicho esto, me atrevo a la lanzar una pregunta que me corroe: ¿ Se podria con todo esto hacer un robot, tanque o cualquier engendro que dentro de un "diorama rectangular" lo colocásemos en cualquier punto (que él reconocería por coordenadas) y siempre sabria llegar por sí mismo al punto 1 (o meta)?
La idea no es descabellada, pero la aplicación con la conjetura Collatz es poco práctica. Si el robot partiese de un número con un tiempo de órbita corto no habría problema, pero supón que, como en el caso de un número como el 27 o el 31 hubiera 111 números en la solución.
El segundo problema es que para coordenadas en un rectángulo necesitas dos números (x,y) ¿Cual sería el segundo número?
Ahora bien, dicho esto, la idea de un robot que encuentra un determinado lugar calculando las coordenadas a partir de su posición inicial me parece muy interesante, aunque nada sencillo.
Cita de: Jetro en 15 de Mayo de 2010, 23:05:26 PM
pero la aplicación con la conjetura Collatz es poco práctica.
Así a bote pronto... un buen ejemplo sería un parking "robotizado", poco importa si el numero de pasos es 1 ó 200 si nos lleva el coche a la puerta
Para el segundo problema siempre podemos pasar de coordenadas cartesianas a polares
(http://static.guim.co.uk/Guardian/business/gallery/2009/jan/16/automotive/xnissan-6163.jpg) es broma.
En serio el problema de los dos numeros no es tan relevante todos los coches de una fila tiene una de las dos coordenadas como constantes (x,1) , que quiero un coche que se que esta en la fila 5 -- (x,5), y ya esta, que es el 27 de la fila 9 (27,9), pues.. ¡señora espere un poco! que su coche va a tardar un "ratito" en llegar
(http://static.guim.co.uk/Guardian/business/gallery/2009/jan/16/automotive/xford-7803.jpg)
para que nos lo trajera a la puerta solo habría que sumar un 1 a su posición X (para que lo sacara al pasillo) y luego darle al boton del Jetro-Collat
Pero como tu has dicho en alguna ocasión, seguro que alguien ya lo ha pensado antes ???
(http://helektron.com/wp-content/uploads/2008/03/parking_automatico.jpg)
Creo que he echo un off-topic o algo así, sorry también por el tamaño de las imagenes
X) Y creo que si me pongo puedo encontrar, al menos, una o ninguna aplicación más.
Pues, ¡a por ello! ;)
He de admitir que nunca me paso por este subforo...
Las matemáticas siempre me han gustado, y estos problemillas o curiosidades me intrigan. Además programo con MatLab, así que he podido seguir bastante bien todo el hilo. Lo que más me cuesta es el lenguaje de programación, más parecido a C+ o Java, que en absoluto conozco.
Es lógico pensar que cualquier número impar al que le sumes uno, se convierte en par; y que cualquier número impar multiplicado por 3 sigue siendo impar (por descomposición en factores); si se pudiera demostrar que la "velocidad" de crecimiento de 3*n+1 es menor que la de decrecimiento de n/2 para cualquier "n", entonces la regla es siempre cierta.
Jetro, quería hacerte una observación acerca del tiempo de órbita, como lo llamas. No lo he pensado demasiado, es más bien una corazonada (tengo un examen el martes, no estoy para pensar en exceso), pero te lo comento por si quieres pensarlo o esperar a que en 3 días lo piense yo mejor.
Si reconstruyo el problema a la inversa (es decir, partiendo de "1"), y lo multiplico por 2 constantemente (pues todo número resulta par, por lo que no puedo salir del ciclo), obtengo todas las potencias de 2 (que, al ser potencias de 2, quizás pudiera esta conjetura tener una aplicación en el código binario, que ahora mismo no viene al caso). El caso es que, desde una potencia de 2, el tiempo de órbita se reduce drásticamente, pues siempre hay que dividir por 2, haciendo decrecer el número siempre. Si diseñas una serie de operaciones que lleven desde un número hasta una potencia de 2, habrás resuelto un problema similar en poco tiempo. Lo que me lleva a pensar que las operaciones de Collatz transforman al número en una potencia de 2 al final (mayor o menor, tardando más o menos). Entonces podría ser interesante estudiar la convergencia de las transformaciones a una curva de las potencias de 2. No tengo muy claro cómo verlo gráficamente...
No se por qué, pero me viene a la cabeza una espiral de valores aproximándose a una curva de potencias de 2. Podría asemejarse a un problema dinámico en el que tenemos una posición inicial X (el número), y una velocidad inicial V (propiedad del número) que nos indica en qué dirección va a avanzar, además de una aceleración A (otra propiedad del número) que vuelve a modificar la trayectoria.
No se si me he conseguido explicar. Es algo más matemático y de análisis de resultados que de programación.
Con esos datos, podrías predecir el tiempo de órbita de cada número, o si el máximo número que aparecerá en su tratamiento estará dentro de una cota o de otra.
Gran trabajo Jetro ;) Siento el tocho que he soltado...
Tranquilo que yo también tengo la cabeza bastante nublada, aunque en mi caso por falta de sueño.
Lo que dices suena bien, pero no acabo de ver cómo encajarlo. A primera vista parece que las potencias de dos tienen relativamente poca incidencia en los números Collatz. Si observas la secuencia en el poster que hice (en este mensaje (http://www.hispalug.com/foro/index.php?topic=10143.msg173664#msg173664)) en el que de hecho calculé los números al revés, verás que hasta 16 todo son potencias de 2, pero después de eso solo 7 de los 32 resultados son potencias de 2 y solo en cada segundo paso sale un ramal impar (64 -> 21, 256 -> 85, 1024 -> 341) y a partir de allí la distancia a la potencia de dos es cada vez mayor...
Bueno, suficiente, que espero tu elaboración sobre el tema porque igual me estoy yendo por un lado completamente diferente a lo que tienes en mente...
Hoy he tenido un examen que me ha exprimido los sesos, así que no estoy demasiado lucido.
Con Collatz tenemos 2 opciones: disminuir el número dividiendo por 2, o aumentarlo multiplicando por 3 y sumando 1. Si queremos llegar hasta "1", lo que tenemos que hacer es disminuir el número. La única operación para disminuirlo es dividir por 2 una y otra vez, hasta obtener un número impar. Entonces, el número más óptimo para llegar lo antes posible al resultado "1" es cualquier potencia de 2, ya que puedes dividir una y otra vez por 2 hasta llegar a "1".
Por eso, antes de llegar al número "1", tendremos que caer por fuerza en una potencia de 2, a partir de la cual caemos en picado hacia el "1".
Entonces podríamos decir que multiplicar por 3 y sumar 1, así como dividir por 2, es todo una "maniobra de aproximación" hacia una potencia de 2.
Si caemos en una potencia de 2, es porque veníamos de un número impar (si fuera par, sería entonces 2*2^n=2^(n+1), por lo que sería una potencia de 2). Entonces tenemos que: 2^n=3*x+1 ==> x=(2^n-1)/3 Esta relación sólo se puede cumplir para unos valores determinados de "n", lo que nos indica que tenemos restringidas las "entradas" a la curva de potencias de 2. Haciendo unas pruebas sencillas:
n=1 --> x=0.33 --> NO
n=2 --> x=1 --> Sí, pero no nos vale porque es el objetivo final: alcanzar el 1; ¡no podemos venir de él!
n=3 --> x=7/3 --> NO
n=4 --> x=5 --> SI
n=5 --> x=31/3 --> NO
n=6 --> x=21 --> SI
n=7 --> x=127/3 --> NO
n=8 --> x=85 --> SI
n=9 --> x=511/3 --> NO
n=10 --> x=341 --> SI
En conclusión se puede ver que sólo podemos "entrar" en las potencias pares de 2, proveniendo de un número impar (al que hemos llamado X ). A su vez, este número impar proviene de un número par irremediablemente (al que llamaremos Y ). ¿Por qué? Porque la "regla" para saber si un número es divisible entre 3 es que la suma de sus cifras sea múltiplo de 3; y si tomamos el número divisible entre 3 y le restamos 1, hacemos que sus cifras dejen de sumar un múltiplo de 3. Además sabemos que cualquier número no divisible por 2, tampoco lo es al multiplicarse por 3 (por simple descomposición en factores). Luego no puede provenir de un número impar.
Y ahora empieza el bucle...
Este número par Y puede provenir de un número impar, o de uno par. Si proviene de unos par, es de la forma Y*2. A su vez, este número puede provenir infinitamente de número pares de la forma Y*2^n, que es una nueva potencia de 2, pero multiplicada por una constante. También puede que este número Y provenga de un número impar (al que llamamos Z) de la forma Y=3*Z+1.
Y lo mismo ocurriría con Z.
Entonces podemos pensar que partimos de un número al que podemos descomponer en un número impar multiplicado por una potencia de 2. Es decir: X=K*2^n, siendo K el número impar. Dividiremos entonces por 2 un número de veces igual a "n", y alcanzaremos el valor K. Como no podemos seguir dividiendo por 2, aplicaremos la otra operación: 3*K+1. Este nuevo número volverá a ser parte de una potencia de 2, de la forma W*2^n, donde W es el nuevo número impar. Repetiremos esta operación una vez tras otra, hasta conseguir que el número impar que multiplique a la potencia de 2 sea igual a "1", nuestro objetivo final.
Así pues, y por fin termino, podemos ver gráficamente como saltamos de un punto a una potencia de 2, y bajamos por ella hasta su punto más bajo; entones volvemos a saltar a otra potencia de 2, la cual volvemos a recorrer hacia abajo hasta su punto más bajo. Y así hasta caer en la potencia de 2 básica: 2^n, cuyo punto más bajo es "1".
Una idea gráfica:
(http://img72.imageshack.us/img72/6708/sinttuloyu.png)
¡Menudo lío! Ahora se podría estudiar el número inicial K, para saber cuánto tardaríamos en llegar hasta "1".
¡Un saludo!
Muy bueno Spazski :}, se nota que con los exámenes la mente trabaja muy bien, por favor sigue.
Este problema da mucho que hablar, hasta suena http://www.youtube.com/watch?v=EEdrNmJ0Euk (http://www.youtube.com/watch?v=EEdrNmJ0Euk)
Y tras una generalización a los complejos nos genera un fractal
La función es equivalente a F(x) = (1+(-1)x)x/4 + (1-(-1)x)(3x+1)/2
Reemplazando (-1)x por cos(x*Pi) y simplificando F(x) = (2+7x-(2+5x)cos(x*Pi))/4
Es una función que podemos iterarla sobre los complejos y analizarla como un fractal
(http://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/CollatzFractal.png/500px-CollatzFractal.png)
en http://en.wikipedia.org/wiki/Collatz_conjecture
Voy a tener que leer esto alguna vez más pero voy viendo a lo que quieres llegar.
Lo del fractal... no sé cómo se me ha pasado ... :D
¡Imresionante! Para que digan que los Legos es un hobby sin aplicaciones prácticas. Gran trabajo, yo también me he puesto a experimentar un poco con la conjetura de este señor, y he encontrado algo curioso: en números consecutivos, hay una tendencia a converger a partir de cierto número. Por ejemplo, 78 y 79; 118 y 119; 156, 157 y 158; 178 y 179; 236, 237 y 238; 246, 247; 268, 269; 278, 279; 256, 257 y 258; 556, 557, 558; 656, 657 658, 659 terminan por converger en el número 304 (que he encontrado completamente al azar). Resulta curioso que, por ejemplo, aparezcan los números:
- 156, 157 y 158
- 256, 257 y 258
- 556, 557 y 558
- 656, 657 y 658
Se omiten algunos números, concretamente cuando el número de las centenas es 0, 3, 4, 5, pero estos convergen en otros números. Pero si se examinan a fondo, todos los números que terminen por
56, 57 y 58 acaban por coincidir en sus últimas iteraciones: 40, 20, 10, 5, 16, 8 4, 2, 1.
No creo que sirva de mucho, pero me ha saltado a la vista al echarle un vistazo a los 91 folios de iteraciones que he calculado (hasta el 1000 X) )
Muy instructivo, sí señor.
Holas;
Cita de: Blastem en 09 de Mayo de 2010, 09:10:12 AM
A esto le llamo yo "quedarse contento" :D
[....]
Pozí.... :D
Jetro, habrás quedado a gusto.... :angel:
Muy bueno todo el trabajo realizado. De todas formas, esto de Lego tiene poco: no hay bricks, sólo has usado el NXT, pero como máquina de cálculo. Curioso, el 9232, ¡qué tendrá....?
Ojo, Jetro, en la leyenda del póster has puesto 3n
-1 para los impares, cuando ha de ser 3n
+1 según tu primer mensaje.
Cita de: Vi en 10 de Agosto de 2010, 21:39:17 PM
Ojo, Jetro, en la leyenda del póster has puesto 3n-1 para los impares, cuando ha de ser 3n+1 según tu primer mensaje.
Si, algunos mas me llamaron la atención sobre eso y lo he corregido en el original... solo que en el primer mensaje no - me sirve para ver si realmente lees lo que escribo X) B)