jueves, 19 de marzo de 2015

Arte con el Spectrum +3: Melody-8 bits-Sincro-Plot-Stock-Market

Qué polvoriento estaba mi Spectrum +3 cuando lo he visto esta mañana en mi casa. He pensado usarlo un poquito para recordar viejos tiempos. Sin corto ni perezoso, he cogido la televisión de mi dormitorio, un ladrón eléctrico, y me he ido a colocarlo al salón de mi casa.
Una vez colocados todos los trastos sobre una mesa plegable, he enchufado la corriente de la TV, la de la fuente de alimentación del Spectrum +3, y he conectado el cable de antena desde el viejuno cumputador a la TV no tan viejuna, pero que todavía soporta canales analógicos. 
Encendiendo los aparatos, no es suficiente para verlos funcionar. Hay que recordar que lo primero que había que hacer era sintonizar el canal de vídeo analógico que sale de la maquinita y llega a la TV. Por tanto, configurando el canal desde el menú de la TV, y tras un rato de búsqueda automática de canales analógicos, esta ha conseguido sintonicar la señal deseada en la pantalla, presentando un menú de inicio con cuatro opciones. En este momento me he dicho, ¡bravo!, funciona!, bueno no del todo, la TV emitía un ruido de fondo no demasiado molesto, y la disquetara parecía no estar en las condiciones de fábrica, porque se ecuchaba también un ruido bastante raro proveniente de su interior. En fin, el tiempo y el trasiego hacen de las suyas a la electrónica, gracias que se sintoniza y el teclado paracía que respondía, por lo menos los cursores.

En ese momento, ya era hora de hacer algo con el micro computador de 8 bits. Pues bien, me sentado delante de ese arcaico teclado, y de la TV no tan antigua, pero bien sintonizada, y el primer problema al que me enfrentadaba era descifrar ese teclado tan diferente de los modernos, y tan specífico para aquellas máquina domésticas. Aunque al menos poseen una distribución QWERTY, el resto de teclas especiales, CONTRO, ESCAPE, SHIFT, BACKSPACE, están en lugares dispares, que responde a razones del maestro que lo creo, nuestro querido y fallecido Sir Clive Sinclair.

Ante mí jeta, una pantalla en blanco se presentaba. Había que echarle imaginación al asunto, porque aunque las opciones con una computadora, como máquina universal son infinitas, tienes su aquel un poco ortopédico, trabajar con aquellas antiguallas. Es estas circunstancias, además del conocimiento técnico de la máquina y del lenguaje que incorpora, la creatividad debe aflorar para poder trabajar con ellas. Es una situación de cubículo, donde no se dispone de internet, y no puedes hacer zapping entre los diferentes contenidos para ayudarte en el avance hacia alguna parte.

He seleccionado la opción de BASIC+3, donde una pantalla blanca y un cursor parpadenate se presentan ante el usuario. Entonces he empezado a recordar el lenguaje que se utilizaba. Era un lenguaje que precisaba un número de línesa al comienzo, y utilizaba comandos bastante básicos en comparación a los lenguajes más modernos. Aún así, incorpora todo lo que se le puede pedir a un lenguaje de programación imperativa, desde la declaración de variables numéricas y alfanuméricas, arrays de datos,  comando de control, como bucles FOR-NEXT y IF-THEN-ELSE, así como subrutunas GOSUB-RETURN y funciones. El nombre del lenguaje BASIC+3, una extensión del BASIC para el Spectrum 48K. Para más información sobre el misno, basta buscar en la wikipedia sobre las especificaciones del lenguaje. 

Era hora de programar algo,  y aleatoriamente, me he puesto ha jugar con el  famosos comando BEEP, que permitía activar el altavoz interno del ordenador. Eran sonido bastante estridentes e insoportables, es decir, apenas se emite un pitido, pero gracias a que el comando dispone de 2 parámetros, uno para fijar la duración y otro la frecuencia, se puede hacer algo más intersante. Al principio, no he hecho mas que la típica escalera de notas, arriba y abajo en frecuencia, pero poco a poco he ido añadiendo cambios, como las funciones matemáticas SIN y RND, que la han hecho más interesante y sofisticada. En esos moento, me recordabam a aquellas melodías que incorporaban los videojuegos de los 80s, o lo que hoy también se llaman 8-BIT Melody. 

El programa introducido ha sido muy sencillo, y escrito sin ninguna planificación y en el momento. Como se ven en la imagen más abaja, son varios bucles anidados, que dan algo de estructura a la melodía computerizada, con varias secciones, cambiando los parámetros en cada sección para los comandos BEEP, BORDER, SIN y RND. Además, he jugado con los gráficos más simple, representando una gráfica pseudo-aleatoria, que se pinta punto a punto estando sicronizada con las diferentes secciones de la melodía. 
El comando mas básico utilizado para pintar en estos antiguos ordenadores era PLOT, el cual admitiía 2 parámetros, la ordenada y la abscisa del plano de la pantalla.  

A continuación, se puede el listado muy básico, que permite reproducir la demo musico-visual explicada:  

Primera parte del Listado (1/2): Melody-8 bits-Sincro-Plot-Stock-Market


La segunda parte del listado (2/2)





Resultado de la ejecuación de mi proto-programa en basic de mi Spectrum +3. La gráfica que sale, puede recordar a la formación de precios en las bolsas de los mercados financieros


Hasta aquí hemos llegado, espero que os haya gustado la entrada del blog. 
Saludetes en 8-bits!!

martes, 13 de enero de 2015

Programando el Cubo de Rubik (I)

Desde un tiempo, me rondaba por la cabeza hacer un programa que resolviera el cubo de Rubik. Hace años, estuve haciendo algunos bocetos, y tirando algunas líneas de código, pero lo dejé a medias, sin completarlo. Voy a retomarlo tratando de trabajar por partes, es decir, documentando mis avances en éste Blog, entrada trás entrada. 

Las fases de trabajo son, desde definir los requisitos del programa, hacer un diseño razonable y  que sea suficientemente flexible. Además, hay que definir cómo implementarlo en  código fuente. Una vez escrito el código, se debería diseñar una batería de pruebas, para verificar la corrección y eficiencia del programa, viendo cómo aplica una estrategias de resolución al cubo físico. Sin más, he pensado en la bien conocidas solución por 3 capas, que se puede encontrar en muchos sitios y foros en internet (http://www.rubikaz.com/).

En principio, no quiero hacer un diseño demasiado genérico, yendo directamente a la resolución concreta del problema del cubo de Rubik. Tampoco quiero hacer una programación imperativa clásica, que sea difícil de seguir, poco clara y farragosa de entender. Esto es para los fanáticos del ensamblador :).
Para que llegue a la gran audiencia, voy utilizar el lenguaje C++, orientado a objetos, correindo bajo Linux/Gnu Debian. La orientación a objetos permite repartir las responsabilidades y encapsulando las diferentes funcionalidades, así como desacoplar lo máximo posible (buen diseño) las tareas a realizar por el programa.

Respecto a los gráficos, no he pensado en nada complejo.  Simplemente voy a trabajar en modo texto, siendo necesario un cubo físico, para comprobar las soluciones en modo texto entregadas por el programa.   

Es muy importante pensar bien cómo representar el cubo, con sus caras, caritas, colores y operaciones de girado. Para ello, voy a utilizar una notación bien conocida por los "profesionales" del cubo de Rubik.  
¿Cómo es esta notación?. Pues bien, desde que el cubo tiene 6 caras, basta asociar a cada cara una letra, o bien una letra con una prima(') . Esto indicará un giro en sentido horario o anti-horario de la cara, según tenga o no prima. Las caras se denotan:

F: Front, B: Back, L: Left, R: Right, U:Up, D: Down

es decir, en castellano, delantera, trasera, izquierda, derecha, arriba y abajo, respectivamente.  

Además, si colocamos un dos delante de una letra, esto indica un giro de 180 grados.



De esta forma, podemos presentar cualquier combinación de movimientos. Veamos un ejemplo a continuación. Suponer que tenemos la siguiente cadena de letras definidas como antes: 

FB2DF'B', 

Esta ristra de caracteres anterior querría decir lo siguiente: 
  1. Giramos la cara delantera 90 grados sentido horario: F
  2. Giramos cara trasera 90 grados sentido horario: B
  3. Giramos cara de abajo 180 grados: 2D
  4. Giramos cara delantera 90' sentido anti-horario: F'
  5. y por último giramos 90 grados la cara trasera en sentido anti-horario: B'
Ahora, pasamos a la parte de la programación, que da título a esta entrada. Un programa en C++, debería ser pensado, con el objetivo de repartir las funcionalidades o responsabilidades requeridas, entre las diferentes clases que lo componen. Por tanto, definamos que es lo que queremos de nuestro programa claramente:
  1. Representar cualquier estado del cubo de Rubik: Situación de cada cara y color.
  2. Mezclador del cubo de Rubik, mediante un número de giros indicado por el usuario.
  3. Buscador de la posición de una carilla cualquiera, ya sea una arista, o un vértice del cubo.
  4. Desarrollar un algoritmo que resuelva  del cubo de Rubik desde cualquier estado.
  5. Aceptar por consola o fichero, la descripción del estado de un cubo de Rubik, a ser resuelto.
  6. Presentar la salida de la estrategia, en notación de Rubik (vista arriba), la solución al cubo desde un estado aleatorio sacado del mezclador, o introducido por el usuario. 
  7. El usuario debe ser capaz de resolver su cubo de Rubik físico, a partir de la solución.

Podríamos pedir más funcionalidades, como puede ser trabajar con diferentes estrategias de resolución y devolver estadísticas para cada una de las estrategias. Incluso, hacer un programa más genérico, que permita trabajar con cubos de lado mayor a tres. No voy a entrar en esas complejidades, hasta que al menos hayamos acabado con una primera versión sencilla, que sea capaz de resolverlo con una estrategia básica.

¿Cómo realizamos el diseño del programa?. Pues bueno, después de jugar con el cubo físico y, garabatear algunos dibujos y diagramas para representar las operaciones y el estado del cubo, he llegado a un diseño de clases para C++ mas o menos bueno. Esto es un proceso algo intuitivo y creativo, así que es difícil de describir ordenadamente. Podría poner aquí esos diagramas, pero no serviría de mucho, ya que son bastante desordenado y subjetivos.
Ahora, veamos cómo el diseño, nos va a permitir distribuir las funcionalidades descritas. Estas podrían estar agrupadas utilizando las siguientes clases de objetos:

  • Clase Cara: Encargada de representar y mantener los colores de las 9 carillas de una cara del cubo de Rubik, además de su disposición.  Es clave en esta clase, es su auto-referencia, para realizar conexiones entre instancias. Esto permitirá pasar información entre las caras conectadas, cuando se realice una operación de girado en alguna de ellas.
  • Clase Rubik: Aglutinará 6 instancias de la clase Cara, además de encapsular las conexiones entre las instancias de las Caras,  y de las operaciones realizadas. 
  • Clase Mezclador: Recibirá una instancia de clase Rubik, operando sobre ella, mezclando los colores mediante operaciones de giro en cada cara del la instancia de Rubik.
  • Clase Estrategia: Encargada de recibir una instancia de Rubik, y aplicar una estrategia de resolución sobre la misma. Deberá entregar la lista de operaciones en notación de Rubik.

Acabamos aquí con esta entrega. En la próxima, continuaremos definiendo las interfaces de las clases del diseño anterior. Espero que os haya gustando. Cualquier sugerencia o pregunta es bienvenida.
Saludos ;)

lunes, 15 de julio de 2013

CURIOSIDADES EN EL HIPERESPACIO


 



Es bien conocida la fórmula del volumen de una hiperesfera de dimensión N. Es posible calcularla de forma exacta a través de la función gamma. 

Ahora bien, suponer que no conociéramos tal fórmula, una primera aproximación sería utilizar los métodos de cuadratura. Pues bien, estos son totalmente inútiles!!, porque su convergencia es muy muy lenta, que decir imposible, ni con el computador mas grande del universo. Curiosamente, los métodos de Monte Carlo (aleatorios), podrían ayudar en el asunto, bastante más satisfactorios en dimensiones altas y bajas incluso, independizándose su orden de convergencia de la dimensión del espacio!. 

Como última curiosidad sobre el volumen de la hiperesfera, si hacemos tender la dimensión del espacio contenedor a infinito, el volumen de la esfera, tiende a 0!!. Sí sí! a 0, y basta observar que tomando límites en su fórmula exacta, porque se tiene una funcion gamma en el denominador y ésta es de orden N factorial. Apenas queda un punto dentro del hipercubo de dimensión N conteniendo a la hiperesfera de dimensión N-1, totalmente contraintuitivo!