Намалюйте криву Дракона


19

Ви ставите завдання на сьогодні: намалюйте криву дракона!

Якщо ви не знаєте, що таке Крива Дракона, ось вам вступне відео ViHart (Дійсно здорово, будь ласка, дивіться!)

Ваше завдання: намалювати криву дракона, повторену не менше 9 разів. Вам не потрібно показувати ітерації від 1 до 9, потрібно лише показати остаточну криву, вироблену після завершення (принаймні) 9 ітерацій. Крива повинна бути намальована як прямі лінії, що з'єднують точки на кривій; висновок повинен відповідати одному із зображень нижче, на якому показано 9 і більше ітерацій (до відображення, обертання, масштабування та зміни ширини лінії, кольору лінії та кольору тла). Вихід повинен бути достатньо великим, щоб окремі лінії та "скриньки", які вони утворюють, можна було відрізнити один від одного; якщо дві лінії не перетинаються в кривій, вони не повинні займати однакові або сусідні пікселі на виході (між ними повинен бути принаймні один піксель фонового зображення). Можна або відобразити зображення на екрані, або зберегти зображення у файлі. Вихід повинен бути графічним - це не може бути мистецтво ASCII.

Найкоротший код у байтах виграє, однак включати директиви для бібліотек не повинні включатися до числа байтів, і ви можете використовувати графічні бібліотеки чи інші бібліотеки, написані на вашу обрану мову, якщо вони були написані перед публікацією.

Будь ласка, додайте зображення результатів вашої програми.

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

Пропустіть цей параграф, якщо ви подивилися відео:Для тих із вас, хто вирішив не дивитись відео, перші 12 ітерацій кривої дракона показані нижче. Для цілей цього завдання крива дракона - це крива, породжена таким правилом: візьміть кінцеву точку поточної кривої, створіть другу криву, повернуту на 90 градусів навколо цієї кінцевої точки, щоб кінцева точка початкової крива - вихідна точка нової кривої, і з'єднайте дві криві в одну криву, де вони зустрічаються. На зображеннях, показаних нижче, кожна нова ітерація генерується обертанням попередньої ітерації на 90 градусів за годинниковою стрілкою навколо кінцевої точки кожної ітерації. Коли крива відображається на екрані, не очевидно, який кінець вважається "кінцевою точкою", однак, коли крива зберігається як масив точок, легко визначити "кінцеву точку" як останню точку в масив.

Мистецтво Ascii цінується, але не приймається. Це графічний вихід, а не ascii-art.


3
Чи є якісь специфікації щодо розміру, фарбування тощо? Оскільки саме точний вихід трохи незрозумілий.
Rɪᴋᴇʀ


6
Я видалив тег кривої дракона, тому що він, схоже, нічого не додав
Синій


3
Це не дублікат; методи програмування для її вирішення зовсім інші (крім, можливо, у вугіллі). Більшість відповідей використовують графічні бібліотеки черепах, які взагалі не працюватимуть в контексті ASCII.

Відповіді:


2

x86, MSDOS, 16 байт

Я написав це деякий час тому, наскільки мені відомо, найменший розпорядок виготовлення фрактала дракона. Він не використовує реальних ітерацій, а накреслює кожен дискретний піксель, що міститься у фракталі, безпосередньо, показуючи остаточне зображення. Він входить до складу багатьох інших крихітних виробництв у цій упаковці . 16-байтна версія була завершенням моїх зусиль, щоб зробити фрактал дракона якомога меншим, починаючи з 2014 року з цього 32-х байтного виробництва .

Hex

14 10 19 CA D1 FA 10 DE 01 D1 CD 10 B4 0C EB F0

Код

S: 
adc al,0x10
sbb dx,cx       
sar dx,0x01 
adc dh,bl
add cx,dx
int 0x10
mov ah,0x0C
jmp short S

скріншот


1
Це ... Дивовижно сказати. Як би я пішов про це?
Дж. Антоніо Перес

Найшвидший спосіб - це DosBox в Інтернеті, twt86.co?c=FBAZytH6EN4B0c0QtAzr8A%3D%3D Ви можете скопіювати джерело тут і скомпілювати його там само. Класичний спосіб - завантажити DosBox (0.74) самостійно і запустити його там. Найреальніший спосіб - отримати завантажувальний MSDos або FreeDos Bootstick (Rufus) та запустити його за справжнім #noemu;)
HellMood

9

Пітон 2/3, 169 167 150 111 98 78 байт

Зауважте, що імпорт не включений до числа байтів, відповідно до специфікацій виклику.

Завдяки @AlexHall за збереження 39 (!) Байтів і @ nedla2004 ще 13

from turtle import*
o=[90]
for z in o*9:o+=[90]+[-x for x in o[::-1]]
fd(5)
for i in o:rt(i);fd(5)

Починається з генерування списку або праворуч (90) і лівим (-90) поворотами, потім проходить список і переміщує черепаху.

Створений вихід: введіть тут опис зображення

EDIT: Якщо це занадто нудно, занадто дивіться, додайте speed(0)прямо перед першим fd(5). Він буде бігати так само, тільки черепаха буде рухатися набагато швидше.


Зображення було б непогано :)
Kritixi Lithos

Чи можете ви опублікувати зображення або знімок екрана? Навіть не ясно, що цей код виводить що-небудь на екран
Дж. Антоніо Перес

Ваше зображення було відрізане
Дж. Антоніо Перес

Потрібно виправити зараз :)
Тео

@AlexHall Дякую! Я знав, що, мабуть, був спосіб зробити цю петлю waaaay коротшою :)
Theo

8

Логотип, 43 байти

for[i 1 512][fd 9 lt :i/(bitand :i -:i)*90]

Спробуйте з перекладачем на веб- сайті http://www.calormen.com/jslogo/#

Для цього використовується той же принцип, що і в моїй попередній відповіді про мистецтво ASCII та формулі на wikipedia, за винятком того, що я змінив напрямок, щоб відповідати зображенню у питанні:

Спочатку висловіть n у формі, k*(2^m)де k - непарне число. Напрямок n-го повороту визначається k mod 4, тобто залишок, що залишився, коли k ділиться на 4. Якщо k mod 4 дорівнює 1, то n-й виток - R L; якщо k mod 4 дорівнює 3, то n-й виток L R

bitand :i -:iзнаходить найменш вагомий шматочок i. Ми ділимо iна це, щоб вирівняти iпотрібну суму, давши потрібне непарне число k. Не потрібно розрізняти лівий і правий повороти; ми просто повертаємо ліворуч на k*90градуси і покладаємось на те, що обертання - це модуль 360 опетона, який виконує для нас модуль.

Вихідні дані

використовувати, htщоб приховати черепаху, якщо потрібно.

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

Вихід (модифікований)

Далі показано, як крива являє собою єдину нитку.

bk 6 for[i 1 512][fd 6 rt :i/(bitand :i -:i)%4*45-90 fd 3 rt :i/(bitand :i -:i)%4*45-90]

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


4

LindenMASM , 51 байт

LindenMASM була мовою, яку я створив для тогочасного завдання, що назавжди буде жити в пісочниці. Він використовує концепцію систем Лінденмайєра для малювання таких речей, як криві Дракона, фрактальні рослини, трикутники Сєрпінського тощо.

Вихідний код такий:

STT
AXI FX
INC 9
SET F 0
RPL X X+YF+
RPL Y -FX-Y
END

Щоб встановити це, n = 6наприклад:

STT
AXI FX
INC 6
SET F 0
RPL X X+YF+
RPL Y -FX-Y
END

Це створює таке зображення через Python 3 turtle:

6 поколінь

Для ітерацій може бути незначна різниця нумерації, оскільки в системі Лінденмайєра перша ітерація - це один рядок. Ось як це виглядає n = 10:

10 поколінь

Просто для розваги, ось як це виглядає з 15 поколіннями (з доданою інструкцією, MOV 2щоб зробити її трохи меншою):

15 поколінь

Як тільки ви отримаєте до 20 поколінь (з MOV 0.5), ви більше не можете бачити рядки, і для створення цього потрібно багато кроків (пари +-та -+не оптимізовані). Ось що ви отримуєте:

20 поколінь

Зауважте, що поточний перекладач може представляти графічні проблеми для меншої кількості поколінь, тобто, можливо, не виводити на екран. На жаль, коли цього інтерпретатора було створено, жодних проблем не було, можлива зміна Python 3 могла спричинити це, або це може бути просто моя система


4

Низький навантаження, 196 байт

()()(<svg width="99" height="147">)S(<g transform="translate):S((33,33)">)S((3,0)rotate)*a(*a(~*)*~("><path d="M0h3" stroke="#"/>)~*a(*)**:(-90)a~^~(90)a~^)*::*:**:*^S(</g>)(:*)::*:**:*^S(</svg>)S

Я подумав, що може бути цікаво спробувати цей виклик в малопотужному езоланге; Недостатнє завантаження досить добре для мови з такою низькою кількістю команд.

Вихід - файл SVG з дуже сильно вкладеними тегами та деякими комбінаціями клавіш для гольфу. Поки що я не знайшов браузера, який би міг відображати його (Firefox висить кілька хвилин, намагаючись завантажити його, і Firefox і Chromium дають порожній екран). Більшість програм для обробки зображень також не можуть його завантажити (що ускладнює перетворення в інший формат), але мені вдалося завантажити його в переглядач зображень Eye of Gnome (який є частиною встановлення за замовчуванням на Ubuntu). Тому я зробив скріншот зображення, щоб ви могли його бачити (фактичне зображення має прозорий фон, але ви не можете насправді зробити прозорий знімок екрана):

Знімок кривої дракона в "Underload"

Нам потрібно чітко вказати розмір зображення. Вибір відповідної орієнтації для зображення, малювання всього в мінімальному законному розмірі та виконання мінімальної кількості ітерацій, визначених викликом, дає нам зображення, яке просто вписується в ширину 99 пікселів, економлячи байт. Приємно, коли все виходить так.

Загальний алгоритм, що використовується для малювання зображення, полягає у підтримці двох змінних (Underload не називає змінних, але я вважав їх як x і y ), обидва спочатку порожні. Потім ми кілька разів замінюємо ( x , y ) на ( x , повертаємо вліво і рухаємося вперед, y ) і ( x , повертаємо праворуч і рухаємося вперед, y ). Після десяти ітерацій і x, і y проводять криву дракона дев'яти ітерацій.

Існує кілька мікрооптимізацій та хитрощів, пов'язаних із недоотриманням. Щоб уникнути занадто великої ворожнечі з вершиною стека, кожної циклічної ітерації, ми починаємо з об'єднання x і y у функцію "повертаємо рядок, створений об'єднанням: x , інструкція повороту, аргумент функції, move- інструкція вперед, і у . " Ця функція займає лише один пробіл у стеці, тому ми можемо дублювати її, викликати її -90як аргумент, поміняти повернене значення під дублікат та викликати його 90як аргумент, щоб отримати нові значення для x та yбез жодного разу доторкатися більше, ніж два найголовніші елементи стека (які, безумовно, є найбільш доступними). Ця функція створюється кодом під час виконання. Сам генератор також генерується кодом під час виконання, щоб він міг повторно використовувати рядок, <g transform="translateякий також використовується для встановлення початку зображення. Спочатку ми генеруємо всі відкриті теги, а потім, оскільки всі закриті теги є справедливими </g>, ми можемо вивести 1024 закритих тегів, просто повторивши рядок, не турбуючись про їх відповідність відкритим тегам. (Ефективне написання чисел у програмі Underload - сама по собі цікава проблема; (:*)::*:**:*це, мабуть, найефективніший спосіб написання 1024, хоча, перекладаючи «2 на потужність (1 + 2 × 2) × 2»).

У нижньому завантаженні немає графічних бібліотек, тому я створюю SVG, використовуючи комбінацію креслярських ліній у фіксованому положенні та обертаючи зображення навколо заданої точки; замість ручки перевертаємо папір. Ідея полягає в тому, що малюючи лінію, обертаючи все зображення, малюючи іншу лінію, знову обертаючи зображення тощо, ми можемо ефективно імітувати графіку черепахи без необхідності робити арифметику або використовувати будь-які графічні бібліотеки, оскільки всі лінії намальовані в тому самому місці. Звичайно, це означає, що у нас є дуже сильно вкладені теги обертання зображення, що бентежить багатьох глядачів SVG.

Стилізація зображення зараховуватиметься до кількості байтів, тому мені потрібно було надати мінімум стилів, необхідних для відображення зображення. Це виявляється stroke="#", що більш-менш перекладається як "лінія повинна бути певного кольору"; це, здається, розширюється, щоб намалювати його чорним кольором. (Зазвичай ви визначаєте колір як, скажімо, "# 000".) Фон за замовчуванням прозорий. Ми не визначаємо ширину обведення, але вибір, вибраний Eye of Gnome, залишає все видиме.

Багато інтерпретаторів Underload борються з цією програмою, наприклад, той, хто випробовує Інтернет, виходить з ладу, оскільки він генерує деякі дуже великі рядки всередині. Однак оригінальний перекладач інтернету Underload працює. (Цікаво, що найперший перекладач був в Інтернеті, тому мова була доступною в Інтернеті, перш ніж її можна було використовувати в режимі офлайн.)

Щось мені трохи неприємно, це те, що тут, здається, є лише 1023 сегмент рядків, і ми очікуємо 1024. Можливо, один із сегментів в кінці не намальований цим алгоритмом (це було б намальовано на наступній ітерації замість цього). Якщо це дискваліфікує, можливо, можливо адаптувати програму, але це може закінчитися значно довше. (Це не так, як цей виклик все одно виграє змагання; вже є кілька коротших заявок.)


4

MATL , 26 байт

0J1_h9:"tPJ*h]hYsXG15Y01ZG

Якщо в двох осях приймаються різні шкали, код можна зменшити до 19 байт:

0J1_h9:"tPJ*h]hYsXG

Наведені нижче цифри відповідають рівній (26-байтній) версії.

Код, наведений вище, створює 9-ту ітерацію (на основі 0), тобто десяте зображення в виклику:

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

Для інших значень змініть 9код на коді або замініть його, iщоб прийняти число як введення користувача. Наприклад, результат для 13:

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

Пояснення

Для цього використовується цикл для поступового побудови масиву кроків, за яким крива йде у складній площині. Наприклад, перші два кроки 1j(вгору) та -1(ліворуч).

У кожній ітерації копіюється масив кроків поки що. Копія масиву зворотне , помножене на 1j(для повороту на 90 градусів), і зчіплюються до оригіналу.

Після циклу сукупна сума кроків дає фактичні точки, які потім побудуються в складній площині.

0                          % Push 0
 J1_h                      % Push array [1j, -1]. This defines the first two steps
     9:                    % Push [1, 2, ..., 9]
       "                   % For each
        t                  %   Duplicate the array of steps so far
         P                 %   Reverse
          J*               %   Multiply by 1j
            h              %   Concatenate horizontally to previous steps
             ]             % End
              h            % Concatenate with the initial 0
               Ys          % Cumulative sum
                 XG        % Plot. Complex numbers are plotted with real and imag as x and y
                   15Y0    % Push string 'equal'
                       1ZG % Set equal scale in the two axes

Ваша відповідь вражає :) Ви не хочете пояснити код?
Дж. Антоніо Перес

@Jorge Дякую! Готово
Луїс Мендо

Надані вами версії "19-байт" та "26-байт" ідентичні. Я припускаю, що тут є помилка копіювання та вставки?

@ ais523 Дійсно! Виправлено зараз, дякую, що помітили. До речі, це можна побачити тут (експериментальний компілятор; може знадобитися оновлення сторінки)
Луїс Мендо

3

Математика 86 байт

{1,-1}
r=Reverse;Graphics@Line@Nest[Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&,{{0,0},%},9]

Як це працює: {1,-1}Виходи {1,-1}. Це в основному "штовхає його до стека". Це значення можна відкликати за допомогою %. r=Reverseв основному просто перейменовує функцію "Зворотний", тому що я її два рази використовую в коді. Graphics@Line@Просто приймає список точок і малює лінію , що сполучає їх. Реальне м'ясо проблеми відбувається в цьому сегменті коду: Nest[Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&,{{0,0},%},9]. Лемме скажу - цей сегмент складний, як f ****** ck. Ось що Nestробить: Nest[f,x,9]виводить результат викликуf[f[f[f[f[f[f[f[f[x]]]]]]]]] .

У моєму коді цей перший аргумент fтакий:, Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&другий аргумент x- це {{0,0},%}(що оцінює {{0,0},{1,-1}}), а третій -n це лише 9 (що просто застосує перший аргумент до другого аргументу 9 разів).

Найскладнішою частиною є цей перший аргумент: Join[l=Last@#;h=#-l&/@#,r[r@#%&/@h]]&- це гігантський безлад майже чистого синтаксичного цукру. Я справді зловживав синтаксичним цукром математики для цього. Цей рядок коду представляє математичну версію анонімної функції, за винятком того, щоб скоротити речі, я фактично визначив дві окремі анонімні функції в межах цієї анонімної функції. Так, законно, люди. Давайте розбимо його.

Joinбере два аргументи. Перший є l=Last@#;h=#-l&/@#, а другий - r[r@#%&/@h].

Перший аргумент Join: Всередині "основної" анонімної функції #- це список усіх точок на поточній ітерації в кривій. Так l=Last@#;означає "Візьміть точку в списку точок, які ви отримали як вхідні дані, і призначте цю точку змінній l. Наступний відрізок, h=#-l&/@#трохи складніший. Це означає," у вас є функція. Ця функція приймає крапку як вхід, віднімає lз неї і повертає результат. Тепер застосуйте цю функцію до кожного елемента у списку точок, які ви отримали як вхід, щоб створити список зміщених точок, і призначте цей новий список змінній h.

Другий аргумент Join: r[r@#%&/@h] має буквально найскладніший синтаксис, який я коли-небудь писав. Я не можу повірити, що будь-який сегмент коду може містити щось подібне @#%&/@- схоже, я проклинаю, як персонаж мультфільму посеред програми! Але можна розбити це. Пам'ятайте - r[x]бере список пунктів і повертає цей список у зворотному порядку. r@#%&це анонімна функція, яка повертає введене в дію, потім помножує його на значення, на %яке покладено (яке є {1,-1}), і повертає результат. В основному він обертається, це вхід на 90 градусів, але в коді такий короткий, як я міг би написати. Потім r@#%&/@hозначає "Вивести новий список, який є кожною крапкою на h90 градусів".

Таким чином, загалом, Join[l=Last@#;h=#-l&/@#,r[r@#*%&/@h]]&це функція, яка приймає список точок як вхідний і додає до цього ж списку точок, повернутих на 90 градусів, щоб отримати наступну ітерацію кривої. Це повторюється 9 разів, щоб отримати криву дракона. Потім отриманий список точок виводиться на екран у вигляді рядка. І вихід:

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


3
Я щойно знайшов найдивніший трюк для написання нульового вектора: 0{,}... працює тому 0 x, що 0майже для будь-якого xі {,}є синтаксичним цукром для {Null,Null}.
Мартін Ендер

3

Python 2, 43 байти

Ця відповідь становить 43 байти, не включаючи заяву про імпорт, і багато в чому ґрунтується на відповіді логотипу Level River St та їх використанні i/(i&-i)у своєму коді. Спробуйте в Інтернеті на сайті trinket.io

from turtle import*
for i in range(1,513):fd(9);rt(90*i/(i&-i))

Ось малюнок виводу.

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


Наскільки я знаю, вам потрібно включити кількість байтів із заяви про імпорт до загального підрахунку байтів.
Тео

1
@Theo, просто цитуючи специфікацію виклику:The shortest code in bytes wins, however include directives for libraries shouldn't be included in the byte count, and you may use graphics libraries or other libraries written for your language of choice if they were written before the posting.
Sherlock9

3

Математика, 56 55 байт

Graphics@Line@AnglePath[Pi/2JacobiSymbol[-1,Range@512]]

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

Пояснення: OEIS A034947

Тільки для задоволення, ось кольорова версія 19-ї ітерації.

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


2

Математика, 63 байти

Використання AnglePath

Graphics@Line@AnglePath[Pi/2Nest[Join[#,{1},-Reverse@#]&,{},9]]

Дев'ять ітерацій


1

HTML + JavaScript, 182

<canvas id=C></canvas><script>c=C.getContext("2d")
C.width=C.height=400
s=n=9
x=y=200
for(i=d=0;i<=1<<n;d+=++i/(i&-i))
c.lineTo(x,y),
d&1?y+=d&2?s:-s:x+=d&2?-s:s
c.stroke()</script>


0

Діаграми Haskell +, 179 байт

import Diagrams.Prelude
import Diagrams.Backend.SVG
d 1=hrule 1<>vrule 1
d n=d(n-1)<>d(n-1)#reverseTrail#rotateBy(1/4)
main=renderSVG"d"(mkWidth 99)$strokeT(d 9::Trail V2 Double)

Вихід - SVG-файл у ширину 99 пікселів з прозорим фоном (зображення в ширину 9 пікселів має би обведення занадто товсте, щоб нічого не відновити). Тут він перероблений і складений на білому тлі:

Дракон номер дев'ять


0

шпигувати , 518 байт

tosh - це Scratch , але з текстом замість блоків. На 518 байт ця відповідь, ймовірно, навіть гірша, ніж у Java.

Ця відповідь використовує ту саму логіку, що і відповідь Pyo на @ Theo , але з рядками "L" та "R" замість чисел, оскільки можливості списку Scratch (і, таким чином, tosh's) у списку жахливі.

Ви можете запустити його як проект Scratch тут . (tosh компілює для проектів Scratch)

when flag clicked
set path to "R"
go to x: -50 y: 100
point in direction 90
pen down
set pen size to 2
clear
repeat 9
    set path copy to path
    set path to join (path) "R"
    set i to length of path copy
    repeat length of path copy
        if letter i of path copy = "R" then
            set path to join (path) "L"
        else
            set path to join (path) "R"
        end
        change i by -1
    end
end
set i to 0
repeat length of path
    change i by 1
    if letter i of path = "R" then
         turn cw 90 degrees
    else
         turn ccw 90 degrees
    end
    move 7 steps
end  

Пояснення:

when flag clicked
set path to "R"
go to x: -50 y: 100
point in direction 90
pen down
set pen size to 2
clear

Ця перша частина змушує програму запускатись, коли клацається зелений прапор ( when flag clicked), встановлюється змінна шлях на "R" і отримує спрайт і етап у належному стані, щоб бути готовим до малювання.

repeat 9
    set path copy to path
    set path to join (path) "R"
    set i to length of path copy
    repeat length of path copy
        if letter i of path copy = "R" then
            set path to join (path) "L"
        else
            set path to join (path) "R"
        end
        change i by -1
    end
end

Тепер ми переходимо до коду генерації шляху. Він використовує ту саму логіку, що і відповідь Pyo на @ Theo , за винятком рядків "R" і "L" замість чисел, і ми використовуємо вкладені цикли замість розуміння списку.

set i to 0
repeat length of path
    change i by 1
    if letter i of path = "R" then
         turn cw 90 degrees
    else
         turn ccw 90 degrees
    end
    move 7 steps
end  

Нарешті, ми намалюємо шлях, пройшовши кожну букву змінної шляху та повернувши вліво або вправо залежно від букви.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.