Animar uma figura de Lissajous rotativa

15

As inscrições para este desafio exibirão uma figura Lissajous rotativa e animada . A aparência da rotação 3d ocorre quando o parâmetro x é sucessivamente mudado de fase em cada quadro.

Entrada:

Os parâmetros ae b(conforme o artigo da wikipedia ) serão especificados na linha de comando ou lidos a partir de stdin.

Resultado:

Isso é , portanto, a saída será exibida em uma janela do emulador de terminal ou equivalente. O tamanho da saída pode ser codificado, mas a figura de Lissajous deve ser pelo menos grande o suficiente para preencher uma janela de 80x24.

A taxa de quadros da animação será de aproximadamente 50 qps. Dormir por 20 ms entre cada quadro é bom, desde que o tempo para calcular cada quadro seja pequeno em comparação com o tempo fixo de sono. Se a sua escolha de idioma não puder ser calculada com rapidez suficiente na plataforma escolhida, você precisará calcular o tempo para dormir dinamicamente.

Cada quadro não será exibido até que todo o cálculo desse quadro esteja completo. Não há necessidade de limpar a tela entre cada quadro.

A figura fará uma 2*Pirotação completa aproximadamente a cada 4 segundos.

Para cada quadro, uma curva fechada completa deve ser gerada. Pelo menos 1000 pontos devem ser calculados ao longo da curva. Não é necessário desenhar linhas entre os pontos.

Os pontos da curva serão plotados como #caracteres. O restante da área de exibição ficará em branco / em branco.

Isso é , então a resposta mais curta em bytes (considerada aceitável por mim) será o vencedor aceito uma semana após esta postagem.


Resposta de referência não destruída .

Trauma Digital
fonte
1
Podemos desenhá-lo usando uma linguagem orientada a gráficos?
TheDoctor
@ TheDoctor Fiquei impressionado com isso, mas decidi restringir a arte ascii . Talvez possamos fazer um acompanhamento da saída gráfica se isso acabar popular.
Digital Trauma
1
Tal como acontece com muitas figuras rotativas, essas figuras rodam de maneiras diferentes, dependendo de como você as vê. Por exemplo, sua resposta parece estar indo e voltando para mim. Mas quando me esforço, consigo ver rotação regular.
30714 Justin

Respostas:

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);}

Os coeficientes são passados ​​através de argumentos. O gif acima é produzido a partir deperl % 2 3

mniip
fonte
1
@DigitalTrauma eu tenho a minha própria ferramenta para gravação de tela no X11
mniip
7

C (resposta de referência - não jogado)

Saída com ./lissajous 2 3:

insira a descrição da imagem aqui

/*
 * 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, bem, eu também não pude resistir ao golfe. Eu acho que há muito mais golfe a ser feito sobre isso:

#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
fonte
2
engraçado como a resposta de referência está ficando upvotes ...
TheDoctor
@ TheDoctor eu sei, certo. Foi por isso que acabei adicionando uma versão em golfe, pois não parecia certo receber votos por uma resposta não-destruída.
Digital Trauma
Se você usleepdeseja 20.000 ms, por que não apenas sleep20 anos?
usar o seguinte comando
usleep @ace (20000) == 20000 micro segundos, não 20000 mili segundos
Trauma Digital
Opa, desculpe, meu mal. Que tal usleep(2e4);?
usar o seguinte comando
2

Python 3 - 280

Não tenha um desses gifs animados para você, desculpe. O console do Windows está lento na impressão: P

Não tenho certeza se isso atende aos requisitos de 50fps, mas não tenho certeza se é realmente possível com o Python. Você pode ajustar o 1000 na segunda linha para a quantidade de pontos a serem calculados (a lista é largura de saída, altura de saída, pontos a serem encontrados, progressão por quadro (pi * 2 / n) e ponto inicial). Ou você pode removê-los e especificar na entrada também.

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

EDIÇÃO MAIS IMPORTANTE: Entrada via stdin, separada por espaço, nova linha terminada. Vai aguardar a sua entrada.

Edição: Screenshot. Altura alterada para 40 para este.

Renderização de Lissajous

cjfaure
fonte
Hmm, ele simplesmente trava para mim com o python 3.2.3 (e 2.7.3) no Ubuntu. Acho que preciso desenterrar uma VM do Windows de algum lugar. Ou aprenda python.
Digital Trauma
@DigitalTrauma Hm. Estou executando o 3.3.2. Estranho que não funcione, não vejo nenhum procedimento específico da plataforma no meu código.
cjfaure
Salvar como lissajous.pye executar python3 lissajous.py 2 3deve ser suficiente, certo?
Digital Trauma
@DigitalTrauma Oh, oh, desculpe. Ele recebe entrada de stdin, não os argumentos (falha ao especificar que ... oops). Espaço separado.
cjfaure
Aha - acho que deveria ter visto input()e adivinhado isso. Agora funciona bem para mim com o 3.2.3. +1
Digital Trauma
1

C # - 360 352 (plataforma cruzada - 332 apenas para Windows)

Editado após correção de bug de micro-golfe e arredondamento + sugestão de Ypnypn

Não é exatamente um candidato nesse sentido - e é praticamente uma cópia literal da referência - mas tudo bem. :)

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);}}}}

Hog de memória, criando uma nova matriz para cada atualização - originalmente (re) usava um StringBuilder, mas o sacrificava por falta de tempo. Mas pelo menos a atualização leva menos de 1 ms no meu antigo Core2.

Depois de remover um pouco do golfe antigo, que agora prejudica o comprimento, reduzindo-o em 8 caracteres, tentei devolvê-lo ao 360 "poético", revertendo para o dobro em vez da análise int e retornando para 80 * 24 em vez de 1920. No entanto, ainda são apenas 359 - e nenhuma outra adição de caractere em que eu consigo pensar realmente agrega valor ao código. Então, vamos ficar com 352. :-)

Desenrolado (perdeu o código de pré-golfe):

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);
                }
            }
        }
    }
}

O console do Windows realmente aceita a saída de muitos caracteres nulos, resultando em uma saída (graficamente) idêntica ao uso de um caractere de espaço real - o que permite que alguns caracteres a menos inicializem a matriz de caracteres.

Nenhuma animação chique, desculpe :-)

JimmiTh
fonte
O console do Windows realmente aceita a saída de muitos caracteres nulos . Ah, talvez isso explique por que não está tão bem com o mono no Ubuntu. Eu não tenho o windows / .net à mão agora, por isso vou aceitar sua palavra para que funcione.
Digital Trauma
Acabei de adicionar uma captura de tela - deve torná-la multiplataforma, mas considerando o status de não-concorrente que já possui - e o número "poético" de caracteres, talvez deva ser deixado como está. :-)
JimmiTh
Não é necessário que todas as respostas sejam IMO entre plataformas. Se as respostas são específicas da plataforma, é bom mencionar a plataforma, embora o C # seja tão conhecido que já seja óbvio.
Digital Trauma
Será que using C = Consolerealmente salvar as personagens?
Ypnypn
@Ypnypn - não depois de invadir o espaço para nome System, não. Não alterou nem procurou, porque o objetivo declarado era obter os mesmos 360 caracteres enquanto ainda usava a inicialização "adequada" do array de caracteres. Obrigado. :-)
JimmiTh
1

Python 2.7 - 214

Eu acho que vou dar outra olhada nisso. Tenho a sensação de que isso pode ser reduzido ainda mais, mas será difícil atingir a contagem de bytes do Perl. A matemática parece ser minha maior limitação aqui.

Aviso: pode travar qualquer terminal que você estiver usando. Eu testei isso no prompt de comando do Windows com lissajous.py 2 3. Devido à rápida gravação no prompt de comando, espere que os quadros pulem um pouco. Isso pode ser resolvido principalmente (ao custo da velocidade) usando um valor maior sno range(s)e t=2*pi*i.

Eu não uso \r ou \baqui intencionalmente porque estou executando no Windows e isso custaria caracteres extras.

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
fonte
+1 Obras no Ubuntu, embora a saída é um pouco nervosa
Digital Trauma
@DigitalTrauma Sim, o salto é causado por ser uma solução de plataforma cruzada (ou seja, para trabalhar no prompt de comando do Windows).
GrovesNL