Animate a Rotating Lissajous Figure

15

Entri untuk tantangan ini akan menampilkan gambar Lissajous berputar yang beranimasi . Tampilan rotasi 3d terjadi ketika parameter x berturut-turut dialihkan fase di setiap frame.

Memasukkan:

The adan bparameter (sesuai artikel wikipedia ) akan ditentukan pada baris perintah, atau membaca dari stdin.

Keluaran:

Ini , jadi output akan ditampilkan di jendela emulator terminal atau yang setara. Ukuran output mungkin hardcoded, tetapi angka Lissajous harus setidaknya cukup besar untuk mengisi jendela 80x24.

Kecepatan bingkai animasi sekitar 50fps. Tidur selama 20 ms antara masing-masing frame baik-baik saja, selama waktu untuk menghitung setiap frame kecil dibandingkan dengan waktu tidur tetap. Jika pilihan bahasa Anda tidak dapat menghitung cukup cepat pada platform yang Anda pilih, maka Anda harus menghitung waktu untuk tidur secara dinamis.

Setiap frame tidak akan ditampilkan sampai semua perhitungan untuk frame itu selesai. Tidak perlu menghapus layar di antara setiap bingkai.

Angka tersebut akan membuat 2*Pirotasi penuh kira-kira setiap 4 detik.

Untuk setiap frame, kurva tertutup penuh harus dihasilkan. Setidaknya 1000 poin harus dihitung di sepanjang kurva. Tidak perlu menggambar garis di antara titik.

Poin kurva akan diplot sebagai #karakter. Sisa area tampilan akan kosong / kosong.

Ini adalah , jadi jawaban terpendek dalam byte (dianggap dapat diterima oleh saya) akan menjadi pemenang yang diterima satu minggu setelah posting ini.


Jawaban referensi tidak disatukan .

Trauma Digital
sumber
1
Apakah kami diizinkan menggambar menggunakan bahasa yang berorientasi grafis?
Dokter
@ TheDoctor saya tidak setuju dengan itu, tetapi memutuskan untuk membatasi ascii-art . Mungkin kita bisa melakukan grafis-output tindak lanjut jika ini populer.
Digital Trauma
1
Seperti halnya banyak angka berputar, angka-angka ini memutar cara yang berbeda tergantung pada bagaimana Anda melihatnya. Sebagai contoh, jawaban Anda tampaknya bergoyang-goyang kepada saya. Tetapi ketika saya berusaha keras, saya bisa melihat rotasi teratur.
Justin

Jawaban:

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

Koefisien diteruskan melalui argumen. Gif di atas dihasilkan dariperl % 2 3

mniip
sumber
1
@DigitalTrauma Saya memiliki alat sendiri untuk layar perekaman di X11
mniip
7

C (jawaban referensi - tidak golf)

Output dengan ./lissajous 2 3:

masukkan deskripsi gambar di sini

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

Oke, saya sendiri tidak bisa menahan diri untuk tidak bermain golf. Saya pikir ada banyak lagi golf yang harus dilakukan dalam hal ini:

#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
sumber
2
lucu bagaimana jawaban referensi semakin meningkat ...
TheDoctor
@ TheDoctor saya tahu, benar. Itulah mengapa saya akhirnya menambahkan versi golf, karena rasanya tidak benar untuk mendapatkan jawaban untuk jawaban yang tidak serigala.
Digital Trauma
Jika Anda membutuhkan usleep20.000 ms, mengapa tidak hanya sleepuntuk 20s?
user12205
@ace usleep (20000) == 20000 mikro detik, bukan 20000 mili detik
Digital Trauma
Ups, maaf, salahku. Bagaimana dengan usleep(2e4);?
user12205
2

Python 3 - 280

Tidak punya salah satu dari gif animasi mewah itu untuk Anda, maaf. Konsol Windows lambat saat mencetak: P.

Tidak yakin ini memenuhi persyaratan 50fps meskipun saya tidak yakin itu benar-benar mungkin dengan Python. Anda dapat menyesuaikan 1000 pada baris kedua untuk jumlah titik yang akan dihitung (daftar adalah lebar keluaran, tinggi keluaran, poin yang akan ditemukan, progresi per frame (pi * 2 / n) dan titik awal). Atau Anda dapat menghapusnya dan menentukan dalam input juga.

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

EDIT LEBIH PENTING: Masukan melalui stdin, dipisahkan oleh ruang, baris dihentikan. Akan menunggu input Anda.

EDIT: Screenshot. Tinggi badan diubah menjadi 40 untuk yang satu ini.

Rendering Lissajous

cjfaure
sumber
Hmm, itu hanya hang untuk saya dengan python 3.2.3 (dan 2.7.3) di Ubuntu. Saya kira saya perlu menggali VM windows dari suatu tempat. Atau belajar python.
Trauma Digital
@DigitalTrauma Hm. Saya menjalankan 3.3.2. Aneh bahwa itu tidak berfungsi, tidak melihat prosedur platform khusus dalam kode saya.
cjfaure
Simpan sebagai lissajous.py, lalu jalankan python3 lissajous.py 2 3harus memadai, bukan?
Trauma Digital
@DigitalTrauma Oh, oh, maaf. Dibutuhkan input dari stdin, bukan args (gagal menentukan bahwa ... oops). Terpisah ruang.
cjfaure
Aha - kurasa aku seharusnya melihat input()dan menebak itu. Sekarang berfungsi dengan baik bagi saya dengan 3.2.3. +1
Trauma Digital
1

C # - 360 352 (lintas platform - 332 hanya untuk Windows)

Diedit setelah micro-golfing dan pembulatan bug + saran oleh Ypnypn

Tidak persis pesaing pada panjang itu - dan itu cukup banyak salinan kata demi kata referensi - tapi oh well. :)

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, membuat larik baru untuk setiap penyegaran - awalnya (kembali) menggunakan StringBuilder, tetapi mengorbankannya untuk mempersingkat. Tapi setidaknya refresh membutuhkan waktu kurang dari 1 ms pada Core2 lama saya.

Setelah menghapus beberapa - lama-menyakitkan - golf lama, sehingga mengurangi dengan 8 karakter, saya mencoba untuk mengembalikannya ke "puitis" 360 dengan kembali ke menggandakan daripada int parsing, dan kembali ke 80 * 24 bukannya 1920. Itu masih hanya 359, meskipun - dan tidak ada penambahan karakter tunggal lain yang dapat saya pikirkan benar-benar menambah nilai pada kode. Jadi kita hanya akan tetap dengan 352. :-)

Belum dibuka (kehilangan kode pra-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);
                }
            }
        }
    }
}

Konsol Windows sebenarnya menerima mengeluarkan banyak karakter nol yang menghasilkan output yang (secara grafis) identik dengan menggunakan karakter ruang aktual - yang memungkinkan beberapa karakter lebih sedikit untuk menginisialisasi array karakter.

Tidak ada animasi mewah, maaf :-)

JimmiTh
sumber
Konsol Windows sebenarnya menerima keluaran banyak karakter nol . Ah mungkin itu menjelaskan mengapa tidak begitu baik dengan mono di Ubuntu. Saya tidak memiliki windows / .net berguna sekarang, jadi saya akan mengambil kata Anda untuk itu berfungsi.
Digital Trauma
Baru saja menambahkan tangkapan layar - harus membuatnya lintas platform, tetapi mengingat status non-pesaing yang dimilikinya - dan jumlah karakter yang "puitis", mungkin harus dibiarkan apa adanya. :-)
JimmiTh
Tidak perlu semua jawaban menjadi IMO lintas platform. Jika jawaban adalah platform-spesifik, ada baiknya menyebutkan platform, meskipun C # sangat terkenal sehingga sudah jelas.
Digital Trauma
Apakah using C = Consolebenar-benar menyimpan karakter?
Ypnypn
@Ypnypn - tidak setelah menyerang namespace Sistem, tidak. Tidak mengubahnya, atau mencarinya, karena tujuan yang dinyatakan sendiri adalah untuk mendapatkan 360 karakter yang sama saat masih menggunakan inisialisasi array char yang "tepat". Terima kasih. :-)
JimmiTh
1

Python 2.7 - 214

Saya pikir saya akan melihat ini lagi. Saya punya perasaan ini bisa diturunkan lebih jauh, tetapi akan sulit untuk mencapai hitungan byte Perl. Matematika tampaknya menjadi batasan terbesar saya di sini.

Peringatan: mungkin macet terminal apa pun yang Anda gunakan. Saya menguji ini pada command prompt Windows dengan lissajous.py 2 3. Karena penulisan cepat ke command prompt, mengharapkan frame untuk melompat sedikit. Ini sebagian besar dapat diselesaikan (dengan biaya kecepatan) dengan menggunakan yang lebih besar sdi range(s)dan t=2*pi*i.

Saya tidak menggunakan \ratau di \bsini dengan sengaja karena saya menjalankannya di Windows dan itu akan memerlukan karakter tambahan.

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
sumber
+1 Bekerja di Ubuntu, meskipun outputnya agak gelisah
Digital Trauma
@ DigitalTrauma Ya kegelisahan disebabkan oleh ini menjadi solusi lintas platform (mis. Untuk bekerja pada command prompt Windows).
grovesNL