Animieren Sie eine rotierende Lissajous-Figur

15

Einträge für diese Herausforderung zeigen eine animierte rotierende Lissajous-Figur . Das Auftreten einer 3D-Drehung tritt auf, wenn der x-Parameter in jedem Frame nacheinander phasenverschoben wird.

Eingang:

Die aund b-Parameter (gemäß dem Wikipedia-Artikel ) werden in der Befehlszeile angegeben oder von stdin gelesen.

Ausgabe:

Dies ist , daher wird die Ausgabe in einem Terminal-Emulator-Fenster oder einem ähnlichen Fenster angezeigt. Die Ausgabegröße kann hartcodiert sein, aber die Lissajous-Zahl muss mindestens groß genug sein, um ein 80 x 24-Fenster auszufüllen.

Die Framerate der Animation beträgt ca. 50 fps. Das Einschlafen für 20 ms zwischen den einzelnen Bildern ist in Ordnung, solange die Zeit zur Berechnung der einzelnen Bilder im Vergleich zur festgelegten Einschlafzeit gering ist. Wenn Ihre Sprachauswahl auf der von Ihnen gewählten Plattform nicht schnell genug berechnet werden kann, müssen Sie die Zeit bis zum Einschlafen dynamisch berechnen.

Jeder Frame wird erst angezeigt, wenn alle Berechnungen für diesen Frame abgeschlossen sind. Zwischen den einzelnen Bildern muss kein Bildschirm gelöscht werden.

Die Figur macht 2*Piungefähr alle 4 Sekunden eine volle Umdrehung.

Für jeden Frame muss eine vollständig geschlossene Kurve generiert werden. Entlang der Kurve müssen mindestens 1000 Punkte berechnet werden. Ein Strichzeichnen zwischen Punkten ist nicht erforderlich.

Punkte der Kurve werden als #Zeichen gezeichnet . Der Rest des Anzeigebereichs ist leer / Leerzeichen.

Dies ist , daher wird die kürzeste Antwort in Bytes (von mir als akzeptabel erachtet) eine Woche nach dieser Veröffentlichung als Gewinner akzeptiert.


Ungolfed Referenzantwort .

Digitales Trauma
quelle
1
Dürfen wir es in einer grafikorientierten Sprache zeichnen?
TheDoctor
@TheDoctor Da war ich hin und her gerissen, aber ich beschloss, mich auf ASCII -Kunst zu beschränken . Vielleicht können wir eine grafische Nachbearbeitung durchführen, wenn dies populär wird.
Digital Trauma
1
Wie bei vielen rotierenden Figuren, drehen sich diese Figuren je nach Ansicht unterschiedlich. Zum Beispiel scheint Ihre Antwort für mich hin und her zu schaukeln. Aber wenn ich mich anstrenge, sehe ich eine regelmäßige Rotation.
Justin

Antworten:

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

Die Koeffizienten werden über Argumente übergeben. Das obige Gif ist hergestellt ausperl % 2 3

mniip
quelle
1
@DigitalTrauma Ich habe mein eigenes Tool für die Bildschirmaufnahme in X11
Mniip
7

C (Referenzantwort - nicht golfen)

Ausgabe mit ./lissajous 2 3:

Bildbeschreibung hier eingeben

/*
 * 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, nun, ich konnte nicht widerstehen, selbst ein bisschen Golf zu spielen. Ich denke, es gibt noch viel mehr zu tun:

#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);}}
Digitales Trauma
quelle
2
lustig, wie die Referenz-Antwort Upvotes bekommt ...
TheDoctor
@TheDoctor Ich weiß, richtig. Aus diesem Grund habe ich eine Golf-Version hinzugefügt, da es nicht richtig erschien, Stimmen für eine ungelöste Antwort zu bekommen.
Digital Trauma
Wenn Sie usleepfür 20000ms sind, warum nicht nur sleepfür 20s?
user12205
@ace usleep (20000) == 20000 Mikro Sekunden nicht 20000 Milli Sekunden
Digitales Trauma
Ups, tut mir leid, mein Schlimmes. Was ist usleep(2e4);?
user12205
2

Python 3 - 280

Du hast leider kein animiertes GIF von dieser Art. Die Windows-Konsole druckt langsam: P

Ich bin mir nicht sicher, ob dies die 50fps-Anforderung erfüllt, obwohl ich nicht sicher bin, ob es mit Python wirklich möglich ist. Sie können die 1000 in der zweiten Zeile für die Anzahl der zu berechnenden Punkte anpassen (die Liste besteht aus Ausgabebreite, Ausgabehöhe, zu findenden Punkten, Fortschritt pro Frame (pi * 2 / n) und Startpunkt). Sie können sie auch entfernen und in der Eingabe angeben.

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

WICHTIGER BEARBEITEN: Eingabe über stdin, durch Leerzeichen getrennt, Zeilenumbruch beendet. Wartet auf Ihre Eingabe.

BEARBEITEN: Screenshot. Die Höhe wurde für diesen auf 40 geändert.

Lissajous Rendering

cjfaure
quelle
Hmm, es hängt für mich nur mit Python 3.2.3 (und 2.7.3) auf Ubuntu. Ich denke, ich muss irgendwo eine Windows-VM ausgraben. Oder lernen Sie Python.
Digital Trauma
@DigitalTrauma Hm. Ich laufe 3.3.2. Seltsamerweise funktioniert es jedoch nicht. In meinem Code werden keine plattformspezifischen Prozeduren angezeigt.
cjfaure
Speichern unter lissajous.py, dann python3 lissajous.py 2 3sollte Ausführen ausreichen, oder?
Digital Trauma
@ DigitalTrauma Oh, oh, sorry. Es werden Eingaben von stdin, nicht von den Argumenten (das konnte nicht angegeben werden ... oops). Raum getrennt.
cjfaure
Aha - das hätte ich wohl sehen input()und erraten sollen. Funktioniert jetzt gut für mich mit 3.2.3. +1
Digitales Trauma
1

C # - 360 352 (plattformübergreifend - 332 nur für Windows)

Bearbeitet nach Micro-Golfing und Rounding Bugfix + Vorschlag von Ypnypn

Nicht gerade ein Konkurrent in dieser Länge - und es ist so ziemlich eine wörtliche Kopie der Referenz - aber na ja. :)

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, das bei jeder Aktualisierung ein neues Array erstellt - ursprünglich (erneut) einen StringBuilder verwendet, ihn aber aus Gründen der Kürze geopfert. Aber zumindest dauert die Aktualisierung auf meinem alten Core2 weniger als 1 ms.

Nachdem ich einiges - inzwischen langwieriges - altes Golfspiel entfernt und es dadurch um 8 Zeichen reduziert hatte, versuchte ich, es wieder auf das "poetische" 360 zurückzubringen, indem ich zu Double anstatt Int-Parsing zurückkehrte und statt 1920 zu 80 * 24 zurückkehrte. Das sind aber immer noch nur 359 - und keine andere, mir einprägsame Einzelzeichenaddition verleiht dem Code wirklich einen Mehrwert. Also bleiben wir einfach bei 352. :-)

Abgerollt (Vorgolfcode verloren):

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

Die Windows-Konsole akzeptiert die Ausgabe vieler Null-Zeichen, was zu einer Ausgabe führt, die (grafisch) mit der Verwendung eines tatsächlichen Leerzeichens identisch ist. Dadurch können wenige Zeichen weniger das Zeichenarray initialisieren.

Keine ausgefallene Animation, sorry :-)

JimmiTh
quelle
Die Windows-Konsole akzeptiert die Ausgabe vieler Nullzeichen . Ah, vielleicht erklärt das, warum es mit Mono unter Ubuntu nicht so gut läuft. Ich habe momentan kein Windows / .net zur Hand, also nehme ich Ihr Wort dafür, dass es funktioniert.
Digital Trauma
Habe gerade einen Screenshot hinzugefügt - sollte es plattformübergreifend machen, aber unter Berücksichtigung des Nicht-Konkurrenten-Status, den es bereits hat - und der eher "poetischen" Anzahl von Charakteren, sollte es vielleicht einfach so bleiben, wie es ist. :-)
JimmiTh
Es ist nicht erforderlich, dass alle Antworten plattformübergreifend sind. Wenn die Antworten plattformspezifisch sind, ist es gut, die Plattform zu erwähnen, obwohl C # so bekannt ist, dass es bereits offensichtlich ist.
Digital Trauma
Hat using C = Consolewirklich alle Zeichen speichern?
Ypnypn
@Ypnypn - nicht nach dem Eindringen in den System-Namespace, nein. Hat es nicht geändert oder danach gesucht, da das selbsterklärte Ziel darin bestand, die gleichen 360 Zeichen zu erreichen, während immer noch die "richtige" Initialisierung des Char-Arrays verwendet wurde. Vielen Dank. :-)
JimmiTh
1

Python 2.7 - 214

Ich glaube, ich werde mir das noch einmal ansehen. Ich habe das Gefühl, dass dies noch weiter gesenkt werden kann, aber es wird schwierig sein, die Perl-Byteanzahl zu erreichen. Die Mathematik scheint hier meine größte Einschränkung zu sein.

Warnung: Möglicherweise stürzt das von Ihnen verwendete Terminal ab. Ich habe dies an der Windows-Eingabeaufforderung mit getestet lissajous.py 2 3. Erwarten Sie aufgrund des schnellen Schreibens in die Eingabeaufforderung, dass die Frames ein wenig springen. Dies kann meistens (auf Kosten der Geschwindigkeit) gelöst werden, indem ein größeres sin range(s)und verwendet wird t=2*pi*i.

Ich benutze \roder \bhier absichtlich nicht, weil ich es unter Windows laufen lasse und es zusätzliche Zeichen kosten würde.

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
HainenNL
quelle
+1 Funktioniert auf Ubuntu, obwohl die Ausgabe etwas nervös ist
Digital Trauma
@DigitalTrauma Ja, die Nervosität wird dadurch verursacht, dass es sich um eine plattformübergreifende Lösung handelt (dh auf der Windows-Eingabeaufforderung zu arbeiten).
GrovesNL