Animar una figura giratoria de Lissajous

15

Las entradas para este desafío mostrarán una figura animada giratoria de Lissajous . La aparición de la rotación 3D se produce cuando el parámetro x se cambia sucesivamente de fase en cada cuadro.

Entrada:

Los parámetros ay b(según el artículo de wikipedia ) se especificarán en la línea de comando o se leerán desde stdin.

Salida:

Esto es , por lo que la salida se mostrará en una ventana de emulador de terminal o equivalente. El tamaño de salida puede estar codificado, pero la figura de Lissajous debe ser al menos lo suficientemente grande como para llenar una ventana de 80x24.

La velocidad de fotogramas de la animación será de aproximadamente 50 fps. Dormir durante 20 ms entre cada cuadro está bien, siempre y cuando el tiempo para calcular cada cuadro sea pequeño en comparación con el tiempo de sueño fijo. Si su elección de idioma no puede calcular lo suficientemente rápido en la plataforma elegida, entonces tendrá que calcular el tiempo para dormir dinámicamente.

Cada cuadro no se mostrará hasta que se complete todo el cálculo para ese cuadro. No hay necesidad de borrar la pantalla entre cada cuadro.

La figura hará una 2*Pirotación completa aproximadamente cada 4 segundos.

Para cada cuadro, se debe generar una curva cerrada completa. Se deben calcular al menos 1000 puntos a lo largo de la curva. No es necesario dibujar líneas entre puntos.

Los puntos de la curva se trazarán como #caracteres. El resto del área de visualización estará en blanco / espacio en blanco.

Este es el , por lo que la respuesta más corta en bytes (considerada aceptable por mí) será el ganador aceptado una semana después de esta publicación.


Respuesta de referencia sin golf .

Trauma digital
fuente
1
¿Se nos permite dibujarlo usando un lenguaje orientado a gráficos?
TheDoctor
@TheDoctor Me desgarré por eso, pero decidí restringirme al ascii-art . Quizás podamos hacer un seguimiento de salida gráfica si esto termina siendo popular.
Trauma digital
1
Al igual que con muchas figuras giratorias, estas figuras rotan de diferentes maneras dependiendo de cómo las mire. Por ejemplo, su respuesta parece mecerse de un lado a otro. Pero cuando me esfuerzo, puedo ver una rotación regular.
Justin

Respuestas:

7

Perl - 177

while($d+=.1){print"\e[H\e[2J";$a=0;while(($a+=.01)<4*atan2 1,0){$x=$==40+40*cos$d+$a*$ARGV[0];$y=$==13+13*sin$d+$a*$ARGV[1];print"\e[$y;$x"."H#";}print$/;select($v,$v,$v,.03);}

Los coeficientes se pasan a través de argumentos. El gif anterior se produce a partir deperl % 2 3

mniip
fuente
1
@ DigitalTrauma Tengo mi propia herramienta para grabar la pantalla en X11
mniip
7

C (respuesta de referencia - sin golf)

Salida con ./lissajous 2 3:

ingrese la descripción de la imagen aquí

/*
 * lissajous.c
 *
 * Compile with:
 *   cc lissajous.c -lm -o lissajous
 *
 * Usage:
 *   ./lissajous a b
 *
 * a and b are the parameters as described in:
 * http://en.wikipedia.org/wiki/Lissajous_curve
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>

int main (int argc, char **argv) {
    char buffer[25][80];
    double t, p;
    int x, y;
    int a, b;

    if (argc != 3) return 1;

    a = atoi(argv[1]);
    b = atoi(argv[2]);

    for (;;) {
        for (p = 0; p < 2 * M_PI; p += M_PI / 100) {
            memset(buffer, ' ', sizeof(buffer));
            /* Set 1st char of final line to nul.  Then we can printf
             * the whole 2d array as if it were one long 1d buffer.
             * Line wraps at 80 chars are assumed */
            buffer[24][0] = 0;
            for (t = 0; t < 2 * M_PI; t += M_PI / 500) {
                x = 39.5 * (1 + sin(a * t + p));
                y = 11.5 * (1 + sin(b * t)); 
                buffer[y][x] = '#';
            }
            printf("%s\n", &buffer[0][0]);
            usleep(20000);
        }
    }
    return (0);
}

C, 257 bytes

Ok, bueno, no pude resistirme un poco al golf. Sin embargo, creo que hay mucho más golf por hacer en esto:

#include<math.h>
main(int a,char**v){char x,y,b,d[25][80];double t,p,q=2*M_PI;a=atoi(v[1]);b=atoi(v[2]);for(p=0;memset(d,32,2000);p+=q/100){p=p<q?p:0;d[24][0]=0;for(t=0;t<q;y=11.5*sin(b*t)+12,d[y][x]=35,t+=q/1e3)x=39.5*sin(a*t+p)+40;puts(d);usleep(20000);}}
Trauma digital
fuente
2
Es curioso cómo la respuesta de referencia está recibiendo votos positivos ...
TheDoctor
@TheDoctor lo sé, cierto. Es por eso que terminé agregando una versión de golf, ya que no me pareció correcto recibir votos a favor de una respuesta no cumplida.
Trauma digital
Si estás usleeppor 20000ms, ¿por qué no solo sleeppor 20s?
user12205
usleep @ace (20000) == 20000 micro segundos, no 20000 mili segundos
Trauma digital
Vaya, lo siento, mi mal. ¿Qué hay de usleep(2e4);?
user12205
2

Python 3 - 280

No tengo uno de esos elegantes gifs animados para ti, lo siento. La consola de Windows es lenta en la impresión: P

No estoy seguro de que esto cumpla con el requisito de 50 fps, aunque no estoy seguro de que sea realmente posible con Python. Puede ajustar el 1000 en la segunda línea para la cantidad de puntos a calcular (la lista es el ancho de salida, la altura de salida, los puntos para encontrar, la progresión por cuadro (pi * 2 / n) y el punto de partida). O puede eliminarlos y especificar también en la entrada.

import math as m
a,b,w,h,p,r,t=list(map(int,input().split()))+[79,24,1000,100,0]
while 1:v,z=w/2,h/2;d=[[int(m.sin(a*k+t)*v+v),int(m.sin(b*k)*z+z)]for k in[m.pi*2/p*l for l in range(p)]];print('\n'.join(''.join([' ','#'][[i,j]in d]for i in range(w))for j in range(h)));t+=m.pi*2/r

EDICIÓN MÁS IMPORTANTE: Entrada a través de stdin, separados por espacios, terminados en nueva línea. Esperaré su aporte.

EDITAR: captura de pantalla. Se cambió la altura a 40 para este.

Renderizado Lissajous

cjfaure
fuente
Hmm, simplemente me cuelga con Python 3.2.3 (y 2.7.3) en Ubuntu. Supongo que necesito desenterrar una máquina virtual de Windows desde algún lugar. O aprende python.
Trauma digital
@DigitalTrauma Hm. Estoy ejecutando 3.3.2. Sin embargo, es extraño que no funcione, no veo ningún procedimiento específico de plataforma en mi código.
cjfaure
Guardar como lissajous.py, luego ejecutar python3 lissajous.py 2 3debería ser suficiente, ¿verdad?
Trauma digital
@DigitalTrauma Oh, oh, lo siento. Toma información de stdin, no de los argumentos (no se pudo especificar que ... oops). Separado por espacios.
cjfaure
Ajá, supongo que debería haberlo visto input()y adivinado. Ahora funciona bien para mí con 3.2.3. +1
Trauma digital
1

C # - 360 352 (multiplataforma - 332 solo para Windows)

Editado después de micro-golf y corrección de errores de redondeo + sugerencia de Ypnypn

No es exactamente un contendiente con esa longitud, y es casi una copia literal de la referencia, pero bueno. :)

namespace System{class P{static int Main(string[]m){double p=Math.PI*2,a=int.Parse(m[0]),b=int.Parse(m[1]),q,t;for(;;)for(q=0;q<p;q+=p/200){var s=new string(' ',1920).ToCharArray();for(t=0;t<p;t+=p/1000)s[(int)(39.5*Math.Sin(a*t+q)+40)+(int)(11.5*Math.Sin(b*t)+12)*80]='#';Console.SetCursorPosition(0,0);Console.Write(s);Threading.Thread.Sleep(20);}}}}

Memory hog, creando una nueva matriz para cada actualización: originalmente (re) usó un StringBuilder, pero lo sacrificó por falta de espacio. Pero al menos la actualización tarda menos de 1 ms en mi antiguo Core2.

Después de eliminar algunos juegos de golf antiguos, que ahora son hirientes, reduciéndolos en 8 caracteres, traté de devolverlos al 360 "poético" volviendo al doble en lugar del análisis interno, y volviendo a 80 * 24 en lugar de 1920. Sin embargo, eso sigue siendo solo 359, y ninguna otra adición de un solo personaje que se me ocurra realmente agrega ningún valor al código. Así que nos quedaremos con 352. :-)

Desenrollado (perdió el código previo al golf):

namespace System
{
    class P
    {
        static int Main(string[] m)
        {
            double p = Math.PI * 2,
                   a = int.Parse(m[0]),
                   b = int.Parse(m[1]),
                   q, t;

            for (;;)
            {
                for (q = 0; q < p; q += p/200)
                {
                    var s = new string(' ', 1920).ToCharArray();
                    // Alternative - Windows console only:
                    // var s = new char[1920];

                    for (t = 0; t < p; t += p/1000)
                    {
                        s[
                            (int) (39.5*Math.Sin(a * t + q) + 40)
                          + (int) (11.5*Math.Sin(b * t) + 12) * 80
                        ] = '#';
                    }
                    Console.SetCursorPosition(0, 0);
                    Console.Write(s);
                    Threading.Thread.Sleep(20);
                }
            }
        }
    }
}

La consola de Windows en realidad acepta generar una gran cantidad de caracteres nulos que resultan en una salida (gráficamente) idéntica al uso de un carácter de espacio real, lo que permite que unos pocos caracteres menos inicialicen la matriz de caracteres.

No hay animación elegante, lo siento :-)

JimmiTh
fuente
La consola de Windows en realidad acepta generar muchos caracteres nulos . Ah, tal vez eso explica por qué no funciona tan bien con mono en Ubuntu. No tengo Windows / .net a mano en este momento, así que aceptaré tu palabra de que funciona.
Trauma digital
Acabo de agregar una captura de pantalla, debería hacerlo multiplataforma, pero teniendo en cuenta el estado de no contendiente que ya tiene, y el número de personajes bastante "poético", tal vez debería dejarse como está. :-)
JimmiTh
No es necesario que todas las respuestas sean IMO multiplataforma. Si las respuestas son específicas de la plataforma, es bueno mencionar la plataforma, aunque C # es tan conocido que ya es obvio.
Trauma digital
¿ using C = ConsoleRealmente salva a algún personaje?
Ypnypn
@Ypnypn: no después de invadir el espacio de nombres del sistema, no. No lo cambié ni lo busqué, porque el objetivo autodefinido era llegar a los mismos 360 caracteres sin dejar de usar la inicialización de matriz de caracteres "adecuada". Gracias. :-)
JimmiTh
1

Python 2.7 - 214

Creo que voy a echar otro vistazo a esto. Tengo la sensación de que esto puede reducirse aún más, pero será difícil alcanzar el recuento de bytes de Perl. Las matemáticas parecen ser mi mayor limitación aquí.

Advertencia: puede bloquearse cualquier terminal que esté utilizando. Probé esto en el símbolo del sistema de Windows con lissajous.py 2 3. Debido a la escritura rápida en el símbolo del sistema, espere que los cuadros salten un poco. Esto se puede resolver principalmente (a costa de la velocidad) utilizando un mayor sen el range(s)y t=2*pi*i.

No lo uso \ro \baquí a propósito porque lo estoy ejecutando en Windows y costaría caracteres adicionales.

from math import*;import sys;a,b=sys.argv[1:];p=s=1920
while p:
 c = [" "]*s
 for i in range(s):
    t=2*pi*i/s;c[int(round((39.5*(1+sin(eval(a)*t+p))))+round(11.5*(1+sin(eval(b)*t)))*80)]="#"
 print ''.join(c)
 p+=.1
grovesNL
fuente
+1 funciona en Ubuntu, aunque la salida es un poco irregular
Digital Trauma
@DigitalTrauma Sí, la agitación es causada por ser una solución multiplataforma (es decir, trabajar en el símbolo del sistema de Windows).
grovesNL