Animare una figura di Lissajous rotante


15

Le voci per questa sfida mostreranno una figura animata rotante di Lissajous . La comparsa della rotazione 3d si verifica quando il parametro x viene successivamente spostato di fase in ciascun fotogramma.

Ingresso:

I parametri ae b(come per l' articolo di Wikipedia ) saranno specificati nella riga di comando o letti da stdin.

Produzione:

Questo è , quindi l'output verrà visualizzato in una finestra dell'emulatore di terminale o equivalente. Le dimensioni dell'output possono essere hardcoded, ma la figura di Lissajous deve essere almeno abbastanza grande da riempire una finestra 80x24.

La frequenza dei fotogrammi dell'animazione sarà di circa 50 fps. Dormire per 20 ms tra ogni fotogramma va bene, purché il tempo di calcolo di ciascun fotogramma sia ridotto rispetto al tempo di sospensione fisso. Se la tua lingua scelta non è in grado di calcolare abbastanza velocemente sulla piattaforma prescelta, dovrai calcolare il tempo di dormire in modo dinamico.

Ogni fotogramma non verrà visualizzato fino al completamento di tutti i calcoli per quel fotogramma. Non è necessario cancellare lo schermo tra ciascun fotogramma.

La figura eseguirà una 2*Pirotazione completa ogni 4 secondi circa.

Per ciascun fotogramma, deve essere generata una curva completamente chiusa. Almeno 1000 punti devono essere calcolati lungo la curva. Non è necessario tracciare la linea tra i punti.

I punti della curva verranno tracciati come #caratteri. Il resto dell'area di visualizzazione sarà vuoto / spazi bianchi.

Questo è , quindi la risposta più breve in byte (ritenuta accettabile da me) sarà il vincitore accettato una settimana dopo questa pubblicazione.


Risposta di riferimento non golfata .


1
Ci è permesso disegnarlo usando un linguaggio orientato alla grafica?
TheDoctor

@TheDoctor Sono stato strappato a questo, ma ho deciso di limitarmi all'ascii -art . Forse possiamo fare un follow-up di output grafico se questo diventa popolare.
Trauma digitale

1
Come con molte figure rotanti, queste figure ruotano in modi diversi a seconda di come le guardi. Ad esempio, la tua risposta sembra oscillare avanti e indietro per me. Ma quando provo duro, posso vedere una rotazione regolare.
Giustino,

Risposte:


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

I coefficienti vengono passati tramite argomenti. Il GIF sopra è prodotto daperl % 2 3


1
@DigitalTrauma Ho il mio strumento personale per la registrazione dello schermo in X11
mniip

7

C (risposta di riferimento - non golfato)

Uscita con ./lissajous 2 3:

inserisci qui la descrizione dell'immagine

/*
 * 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 byte

Ok, beh, non ho potuto resistere un po 'al golf. Penso che ci sia molto più golf da fare su questo però:

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

2
divertente come la risposta di riferimento stia ottenendo voti ...
TheDoctor

@TheDoctor Lo so, giusto. Ecco perché ho finito per aggiungere una versione da golf, dato che non mi sembrava giusto ottenere voti positivi per una risposta non soddisfatta.
Trauma digitale

Se stai usleepusando 20000ms, perché non solo sleepper 20s?
user12205

@ace usleep (20000) == 20000 micro secondi, non 20000 milli secondi
Digital Trauma

Oops, scusa, mia cattiva. Che dire usleep(2e4);?
user12205

2

Python 3 - 280

Non fare una di quelle fantastiche gif animate per te, scusa. La console di Windows è lenta nella stampa: P

Non sono sicuro che questo soddisfi i requisiti di 50 fps, anche se non sono sicuro che sia davvero possibile con Python. È possibile regolare 1000 sulla seconda riga per la quantità di punti da calcolare (l'elenco è la larghezza di output, l'altezza di output, i punti da trovare, la progressione per frame (pi * 2 / n) e il punto di partenza). Oppure puoi rimuoverli e specificare anche nell'input.

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

MODIFICA PIÙ IMPORTANTE: input tramite stdin, spazio separato, newline terminato. Aspetterà il tuo contributo.

EDIT: Screenshot. Altezza modificata a 40 per questo.

Rendering di Lissajous


Hmm, si blocca solo con Python 3.2.3 (e 2.7.3) su Ubuntu. Immagino di dover scavare una VM di Windows da qualche parte. O impara Python.
Trauma digitale

@DigitalTrauma Hm. Sto correndo 3.3.2. Strano che non funzioni però, non vedo alcuna procedura specifica per la piattaforma nel mio codice.
cjfaure,

Salva come lissajous.py, quindi eseguire python3 lissajous.py 2 3dovrebbe essere sufficiente, giusto?
Trauma digitale

@DigitalTrauma Oh, oh, scusa. Prende input da stdinnon args (non è riuscito a specificare che ... oops). Separato da spazi.
cjfaure,

Aha - Immagino che avrei dovuto vederlo input()e indovinarlo. Funziona bene ora per me con 3.2.3. +1
Trauma digitale

1

C # - 360 352 (multipiattaforma - 332 solo per Windows)

A cura di micro-golf e correzione degli errori di arrotondamento + suggerimento di Ypnypn

Non esattamente un contendente a quella lunghezza - ed è praticamente una copia testuale del riferimento - ma vabbè. :)

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 un nuovo array per ogni aggiornamento: originariamente (ri) utilizzava StringBuilder, ma lo sacrificava per brevità. Ma almeno l'aggiornamento richiede meno di 1 ms sul mio vecchio Core2.

Dopo aver rimosso un po 'di vecchio golf, ormai dannoso per la lunghezza, riducendolo di 8 caratteri, ho cercato di riportarlo al "poetico" 360 tornando al doppio anziché all'analisi, e tornando a 80 * 24 invece del 1920. Sono comunque solo 359 - e nessun'altra aggiunta a singolo carattere a cui posso pensare aggiunge davvero alcun valore al codice. Quindi continueremo con 352. :-)

Srotolato (perso il codice pre-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 console di Windows in realtà accetta l'output di molti caratteri null con conseguente output (graficamente) identico all'uso di un carattere spazio reale - che consente a pochi caratteri in meno di inizializzare l'array di caratteri.

Nessuna animazione di fantasia, scusa :-)


La console di Windows in realtà accetta l'output di molti caratteri null . Ah forse questo spiega perché non funziona così bene con Mono su Ubuntu. Non ho Windows / .net a portata di mano in questo momento, quindi prenderò la tua parola per farlo che funzioni.
Trauma digitale

Ho appena aggiunto uno screenshot - dovrebbe renderlo multipiattaforma, ma considerando lo stato di non contendente che ha già - e il numero piuttosto "poetico" di personaggi, forse dovrebbe essere lasciato così com'è. :-)
JimmiTh

Non è necessario che tutte le risposte siano IMO multipiattaforma. Se le risposte sono specifiche della piattaforma, è bene menzionare la piattaforma, anche se C # è così noto che è già ovvio.
Trauma digitale

Fa using C = Consoledavvero salvare qualsiasi carattere?
Ypnypn,

@Ypnypn - non dopo aver invaso lo spazio dei nomi di sistema, no. Non l'ho modificato, né cercato, perché l'obiettivo dichiarato era quello di arrivare agli stessi 360 caratteri mentre si utilizzava ancora l'inizializzazione "corretta" dell'array di caratteri. Grazie. :-)
Jimmi,

1

Python 2.7 - 214

Penso che avrò un'altra occhiata a questo. Ho la sensazione che questo possa essere ulteriormente ridotto, ma sarà difficile raggiungere il conteggio dei byte Perl. La matematica sembra essere la mia più grande limitazione qui.

Attenzione: potrebbe arrestarsi in modo anomalo qualunque terminale si stia utilizzando. Ho provato questo sul prompt dei comandi di Windows con lissajous.py 2 3. A causa della rapida scrittura sul prompt dei comandi, aspettati che i frame saltino un po '. Questo può essere risolto principalmente (a scapito della velocità) usando un maggiore sin range(s)e t=2*pi*i.

Non lo uso \ro di \bproposito perché lo sto eseguendo su Windows e costerebbe caratteri extra.

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

+1 Funziona su Ubuntu, anche se l'output è un po 'nervoso
Digital Trauma,

@DigitalTrauma Sì, il nervosismo è causato dal fatto che si tratta di una soluzione multipiattaforma (ad es. Per funzionare sul prompt dei comandi di Windows).
Grove
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.