Анимируй вращающуюся фигуру Лиссажу

15

Записи для этого испытания будут отображать анимированную вращающуюся фигуру Лиссажу . Появление трехмерного вращения происходит, когда параметр x последовательно сдвинут по фазе в каждом кадре.

Входные данные:

Параметры aи b(согласно статье в википедии ) будут указаны в командной строке или прочитаны из стандартного ввода.

Выход:

Это , поэтому выходные данные будут отображаться в окне эмулятора терминала или аналогичном. Размер вывода может быть жестко задан, но число Лиссажу должно быть как минимум достаточно большим, чтобы заполнить окно размером 80x24.

Частота кадров анимации будет примерно 50 кадров в секунду. Хорошо спать по 20 мс между каждым кадром, если время для расчета каждого кадра мало по сравнению с фиксированным временем ожидания. Если выбранный вами язык не может достаточно быстро рассчитаться на выбранной вами платформе, вам придется рассчитывать время для динамического сна.

Каждый кадр не будет отображаться, пока все вычисления для этого кадра не будут завершены. Нет необходимости очищать экран между кадрами.

Фигура будет совершать полный 2*Piоборот примерно каждые 4 секунды.

Для каждого кадра должна быть сформирована полная замкнутая кривая. Не менее 1000 точек должны быть рассчитаны вдоль кривой. Рисование линий между точками не требуется.

Точки кривой будут отображаться как #символы. Остальная часть области отображения будет пустой / пробел.

Это , поэтому самый короткий ответ в байтах (который я считаю приемлемым) будет признан победителем через неделю после публикации.


Беззвучный справочный ответ .

Цифровая травма
источник
1
Разрешено ли рисовать его с помощью графически ориентированного языка?
TheDoctor
@TheDoctor Я разорвался на это, но решил ограничиться ascii-art . Возможно, мы сможем сделать продолжение с графическим выводом , если это станет популярным.
Цифровая травма
1
Как и во многих вращающихся фигурах, эти фигуры вращаются по-разному в зависимости от того, как вы на них смотрите. Например, ваш ответ, кажется, раскачивается взад-вперед для меня. Но когда я стараюсь, я вижу регулярное вращение.
Джастин

Ответы:

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

Коэффициенты передаются через аргументы. Выше GIF производится изperl % 2 3

МНИИП
источник
1
@DigitalTrauma У меня есть свой собственный инструмент для записи экрана в X11
mniip
7

С (справочный ответ - не в гольф)

Вывод с ./lissajous 2 3:

введите описание изображения здесь

/*
 * 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 байт

Ладно, я не мог удержаться от игры в гольф сам. Я думаю, что на этом можно сделать гораздо больше:

#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
Забавно, как эталонный ответ получает голоса ...
TheDoctor
@ Доктор, я знаю, верно. Вот почему я закончил тем, что добавил версию для игры в гольф, так как было неуместно получать голоса без ответа.
Цифровая травма
Если вы usleep 20000 мс, почему бы не sleep20 с?
user12205
@ace USleep (20000) == 20000 микро секунд, а не 20000 милли секунд
Цифровой Травма
Ой, простите, мой плохой. Как насчет usleep(2e4);?
user12205
2

Питон 3 - 280

Извините, у вас нет одного из этих модных анимированных гифок. Консоль Windows медленно печатает: P

Не уверен, что это соответствует требованию 50fps, хотя я не уверен, что это действительно возможно с Python. Вы можете отрегулировать 1000 во второй строке для количества точек, которые нужно вычислить (список содержит ширину вывода, высоту вывода, точки, которые нужно найти, прогрессию на кадр (pi * 2 / n) и начальную точку). Или вы можете удалить их и указать во входных данных.

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

БОЛЬШЕ ВАЖНОГО РЕДАКТИРОВАНИЯ: ввод через stdin, через пробел, перевод строки завершен. Будем ждать вашего ввода.

РЕДАКТИРОВАТЬ: Скриншот. Изменена высота до 40 для этого.

Лиссажу рендеринг

cjfaure
источник
Хм, это просто зависает для меня с python 3.2.3 (и 2.7.3) на Ubuntu. Я думаю, мне нужно выкопать Windows VM откуда-то. Или выучить питон.
Цифровая травма
@DigitalTrauma Хм. Я бегу 3.3.2. Странно, что это не работает, хотя я не вижу каких-либо платформо-зависимых процедур в моем коде.
cjfaure
Сохранить как lissajous.py, а затем запустить python3 lissajous.py 2 3должно быть достаточно, верно?
Цифровая травма
@DigitalTrauma Ой, о, прости. Он принимает входные данные stdin, а не аргументы (не удалось указать, что ... упс). Пространственно-отделенный.
cjfaure
Ага - наверное, я должен был это увидеть input()и угадать. Теперь у меня нормально работает с 3.2.3. +1
цифровая травма
1

C # - 360 352 (кросс-платформенный - 332 только для Windows)

Отредактировано после микро-игры в гольф и исправления ошибок округления + предложение от Ypnypn

Не совсем претендент такой длины - и это в значительной степени дословная копия ссылки - ну да ладно. :)

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

Захват памяти, создание нового массива для каждого обновления - изначально (пере) использовал StringBuilder, но пожертвовал им ради краткости. Но по крайней мере обновление занимает менее 1 мс на моем старом Core2.

После удаления некоторого - ныне обидного - старого игры в гольф, тем самым уменьшив его на 8 символов, я попытался вернуть его к «поэтическому» 360, вернувшись к удвоению, а не к разбору, и вернувшись к 80 * 24 вместо 1920. Это все еще только 359 - и никакое другое односимвольное дополнение, о котором я могу думать, действительно не добавляет никакой ценности к коду. Поэтому мы будем придерживаться 352. :-)

Развернутый (потерял код перед игрой в гольф):

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

Консоль Windows фактически допускает вывод множества нулевых символов, в результате чего вывод (графически) идентичен использованию фактического пробела - что позволяет инициализировать массив символов на несколько символов меньше.

Никакой необычной анимации, извините :-)

JimmiTh
источник
Консоль Windows фактически принимает вывод множества нулевых символов . Ах, возможно, это объясняет, почему это не так хорошо с моно на Ubuntu. У меня под рукой нет windows / .net, так что поверьте на слово, что это работает.
Цифровая травма
Просто добавили скриншот - должен сделать его кроссплатформенным, но учитывая уже имеющийся у него статус неконтроллера - и довольно «поэтическое» количество символов, возможно, его следует просто оставить как есть. :-)
JimmiTh
Не нужно, чтобы все ответы были кроссплатформенными IMO. Если ответы зависят от платформы, хорошо упомянуть платформу, хотя C # настолько известен, что уже очевиден.
Цифровая травма
using C = ConsoleДействительно ли сохранить какие-либо символы?
Ypnypn
@Ypnypn - не после вторжения в пространство имен System, нет. Не меняйте его и не ищите, потому что самоутвержденной целью было получить те же 360 символов, все еще используя «правильную» инициализацию массива символов. Благодарю. :-)
JimmiTh
1

Python 2.7 - 214

Я думаю, что я собираюсь еще раз взглянуть на это. У меня есть ощущение, что это может быть снижено еще дальше, но будет трудно достичь количества байтов Perl. Математика, кажется, мое самое большое ограничение здесь.

Предупреждение: может произойти сбой любого терминала, который вы используете. Я проверил это в командной строке Windows с lissajous.py 2 3. Из-за быстрой записи в командную строку ожидайте, что кадры немного подпрыгнут. Это может быть в основном решено (за счет скорости) с помощью большего sв range(s)иt=2*pi*i .

Я не использую \rили \bздесь специально, потому что я запускаю его на Windows, и это будет стоить дополнительных символов.

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
источник
+1 Работает на Ubuntu, хотя вывод немного нервный
Digital Trauma
@DigitalTrauma Да, скачок вызван тем, что это кроссплатформенное решение (т. Е. Работа в командной строке Windows).
grovesNL