Animer une figure lissajous rotative

15

Les entrées pour ce défi afficheront une figure animée Lissajous en rotation . L'apparition d'une rotation 3D se produit lorsque le paramètre x est successivement déphasé dans chaque image.

Contribution:

Les paramètres aet b(selon l' article de wikipedia ) seront spécifiés sur la ligne de commande, ou lus depuis stdin.

Production:

C'est , donc la sortie sera affichée dans une fenêtre d'émulateur de terminal ou équivalent. La taille de sortie peut être codée en dur, mais le chiffre Lissajous doit être au moins assez grand pour remplir une fenêtre de 80x24.

La fréquence d'images d'animation sera d'environ 50 images par seconde. Dormir pendant 20 ms entre chaque image est bien, tant que le temps de calcul de chaque image est petit par rapport au temps de sommeil fixe. Si votre choix de langue ne peut pas calculer assez rapidement sur la plate-forme que vous avez choisie, vous devrez calculer le temps de sommeil de manière dynamique.

Chaque cadre ne sera affiché que lorsque tous les calculs pour ce cadre seront terminés. Il n'est pas nécessaire d'effacer l'écran entre chaque image.

La figurine effectuera une 2*Pirotation complète toutes les 4 secondes environ.

Pour chaque image, une courbe fermée complète doit être générée. Au moins 1 000 points doivent être calculés le long de la courbe. Le dessin au trait entre les points n'est pas nécessaire.

Les points de la courbe seront tracés sous forme de #caractères. Le reste de la zone d'affichage sera vide / blanc.

Il s'agit de , donc la réponse la plus courte en octets (jugée acceptable par moi) sera le gagnant accepté une semaine après cette publication.


Réponse de référence non golfée .

Traumatisme numérique
la source
1
Sommes-nous autorisés à le dessiner en utilisant un langage graphique?
TheDoctor
@TheDoctor J'étais déchiré à ce sujet, mais j'ai décidé de me limiter à l' ascii-art . Peut-être que nous pouvons faire un suivi de sortie graphique si cela se révèle populaire.
Digital Trauma
1
Comme avec de nombreuses figurines en rotation, ces figures tournent de différentes manières selon la façon dont vous les regardez. Par exemple, votre réponse semble me basculer d'avant en arrière. Mais quand j'essaye dur, je peux voir une rotation régulière.
Justin

Réponses:

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

Les coefficients sont transmis via des arguments. Le gif ci-dessus est produit à partir deperl % 2 3

mniip
la source
1
@DigitalTrauma J'ai mon propre outil d'enregistrement d'écran en X11
mniip
7

C (réponse de référence - pas joué au golf)

Sortie avec ./lissajous 2 3:

entrez la description de l'image ici

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

D'accord, je n'ai pas pu résister un peu au golf moi-même. Je pense qu'il y a encore beaucoup de golf à faire à ce sujet:

#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);}}
Traumatisme numérique
la source
2
drôle comment la réponse de référence obtient des votes positifs ...
TheDoctor
@TheDoctor je sais, à droite. C'est pourquoi j'ai fini par ajouter une version golfée, car il ne me semblait pas juste d'obtenir des votes positifs pour une réponse non golfée.
Digital Trauma
Si vous êtes usleepà 20000 ms, pourquoi pas seulement sleepà 20 ans?
user12205
@ace usleep (20000) == 20000 micro secondes, pas 20000 milli secondes
Digital Trauma
Oups, désolé, ma mauvaise. Et alors usleep(2e4);?
user12205
2

Python 3 - 280

N'ayez pas l'un de ces gifs animés fantaisie pour vous, désolé. La console Windows est lente à imprimer: P

Je ne suis pas sûr que cela réponde à l'exigence de 50 images par seconde, mais je ne suis pas sûr que ce soit vraiment possible avec Python. Vous pouvez ajuster le 1000 sur la deuxième ligne pour la quantité de points à calculer (la liste est la largeur de sortie, la hauteur de sortie, les points à trouver, la progression par image (pi * 2 / n) et le point de départ). Vous pouvez également les supprimer et les spécifier également dans l'entrée.

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

MODIFICATION PLUS IMPORTANTE: Entrée via stdin, espace séparé, fin de ligne. Attendra votre entrée.

EDIT: Capture d'écran. Changé la hauteur à 40 pour celui-ci.

Rendu lissajous

cjfaure
la source
Hmm, il se bloque juste pour moi avec python 3.2.3 (et 2.7.3) sur Ubuntu. Je suppose que j'ai besoin de déterrer une machine virtuelle Windows quelque part. Ou apprenez le python.
Digital Trauma
@DigitalTrauma Hm. J'utilise 3.3.2. Étrange que cela ne fonctionne pas, je ne vois aucune procédure spécifique à la plate-forme dans mon code.
cjfaure
Enregistrer sous lissajous.py, puis exécuter python3 lissajous.py 2 3devrait être suffisant, non?
Digital Trauma
@DigitalTrauma Oh, oh, désolé. Il prend l'entrée de stdin, pas les arguments (n'a pas pu spécifier que ... oups). Séparé de l'espace.
cjfaure
Aha - Je suppose que j'aurais dû voir input()et deviner cela. Fonctionne bien maintenant pour moi avec 3.2.3. +1
Digital Trauma
1

C # - 360 352 (multiplateforme - 332 pour Windows uniquement)

Modifié après correction d'un bug de micro-golf et d'arrondi + suggestion par Ypnypn

Pas exactement un concurrent à cette longueur - et c'est à peu près une copie textuelle de la référence - mais eh bien. :)

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 mémoire, créant un nouveau tableau pour chaque rafraîchissement - à l'origine (ré) utilisé un StringBuilder, mais sacrifié pour la brièveté. Mais au moins le rafraîchissement prend moins de 1 ms sur mon ancien Core2.

Après avoir supprimé un peu de golf ancien - qui fait mal à la longueur, le réduisant ainsi de 8 caractères, j'ai essayé de le ramener au 360 "poétique" en revenant au double plutôt qu'à l'analyse syntaxique, et en revenant à 80 * 24 au lieu de 1920. Ce n'est toujours que 359, cependant - et aucun autre ajout de caractère unique auquel je peux penser n'apporte vraiment de valeur au code. Nous allons donc nous contenter de 352. :-)

Déroulé (perdu le code pré-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 Windows accepte en fait la sortie d'un grand nombre de caractères nuls, ce qui donne une sortie (graphiquement) identique à l'utilisation d'un caractère d'espace réel - ce qui permet à quelques caractères de moins d'initialiser le tableau de caractères.

Aucune animation de fantaisie, désolé :-)

JimmiTh
la source
La console Windows accepte en fait la sortie d'un grand nombre de caractères nuls . Ah peut-être que cela explique pourquoi ça ne marche pas si bien avec mono sur Ubuntu. Je n'ai pas Windows / .net à portée de main en ce moment, donc je vais vous croire sur parole que cela fonctionne.
Digital Trauma
Nous venons d'ajouter une capture d'écran - cela devrait en faire une plate-forme croisée, mais compte tenu du statut de non-concurrent qu'il a déjà - et du nombre plutôt "poétique" de caractères, il faudrait peut-être le laisser tel quel. :-)
JimmiTh
Pas besoin que toutes les réponses soient OMI multiplateforme. Si les réponses sont spécifiques à la plate-forme, il est bon de mentionner la plate-forme, bien que C # soit si bien connu qu'il soit déjà évident.
Digital Trauma
using C = ConsoleEnregistre- t-il vraiment des personnages?
Ypnypn
@Ypnypn - pas après avoir envahi l'espace de noms System, non. Je ne l'ai pas modifié, ni cherché, car l'objectif déclaré était d'obtenir les mêmes 360 caractères tout en utilisant l'initialisation "correcte" du tableau de caractères. Merci. :-)
JimmiTh
1

Python 2.7 - 214

Je pense que je vais revoir cela. J'ai le sentiment que cela peut être réduit encore plus, mais il sera difficile d'atteindre le nombre d'octets Perl. Les mathématiques semblent être ma plus grande limitation ici.

Avertissement: peut planter le terminal que vous utilisez. J'ai testé cela sur l'invite de commande Windows avec lissajous.py 2 3. En raison de l'écriture rapide dans l'invite de commandes, attendez-vous à ce que les cadres sautent un peu. Cela peut être principalement résolu (au prix de la vitesse) en utilisant un plus grand sdans le range(s)et t=2*pi*i.

Je n'utilise pas \rou \bici à dessein parce que je l'exécute sur Windows et cela coûterait des caractères supplémentaires.

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
la source
+1 Fonctionne sur Ubuntu, bien que la sortie soit un peu nerveuse
Digital Trauma
@DigitalTrauma Oui, la nervosité est causée par le fait qu'il s'agit d'une solution multiplateforme (c'est-à-dire pour fonctionner sur l'invite de commande Windows).
grovesNL