Мені подобаються піфагорійські дерева


17

... тож це виклик зробити мене деревом.

Створіть програму або функцію під назвою дерево, яке приймає єдиний цілий аргумент, N та малює піфагорійське дерево N рівнів глибоко, де рівень 0 - це лише стовбур.

Кожен стик дерева повинен розміщувати вершину трикутника у випадковій точці по периметру (ця точка повинна бути рівномірно розподілена принаймні на 5 однаково розташованих точок або рівномірно по всьому півколу).

За бажанням ваше дерево може бути 3d, бути кольоровим або бути освітленим відповідно до часу доби. Однак це код-гольф, тому виграє найменший файл.

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



Помилковий. Я за іншим алгоритмом :)
alexander-brett

Добре. Справедливо. Ви можете розглянути можливість повернення подання до «Піфагорійського дерева».
DavidC

Я люблю поїзда? :)
tomsmeding

Відповіді:


15

Математика, 246 234 221 символ

g[n_,s_:1]:={p=RandomReal[q=Pi/2],r=##~Rotate~(o={0,0})&,t=Translate}~With~If[n<0,{},Join[#~t~{0,s}&/@(#~r~p&)/@g[n-1,s*Cos@p],t[#,s{Cos@p^2,1+Sin[2p]/2}]&/@(r[#,p-q]&)/@g[n-1,s*Sin@p],{Rectangle[o,o+s]}]]
f=Graphics@g@#&

Це, звичайно, не найелегантніший / найкоротший спосіб зробити це.

Використання: f[8]

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

Ось приклади виходів для f[6]і f[10]відповідно.

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

Дещо незворушний:

g[n_, s_:1] := With[{p},
  r = Rotate;
  t = Translate;
  p = RandomReal[q = Pi/2];
  If[n < 0, {},
   Join[
    (t[#, {0, s}] &) /@ (r[#, p, {0, 0}] &) /@ g[n - 1, s*Cos[p]],
    (t[#, s {Cos[p]^2, 1 + Sin[2 p]/2}] &) /@ (r[#, p - q, {0, 0}] &) /@
       g[n - 1, s*Sin[p]],
    {Rectangle[{0, 0}, {s, s}]}
    ]
   ]
  ]
f = Graphics@g[#] &

Це дуже вражає. Сором, я не маю математики, щоб перевірити це - ви могли б додати ще пару прикладних результатів?
Олександр-Бретт

@ ali0sha див. редагувати
Мартін Ендер

Вам не потрібно Showтам, і Moduleце теж непотрібно.
швейцарський

@swish Дякую за Showпідказку, але як я можу позбутися Module? Якщо я не оголошу pлокальний, він буде перезаписаний у рекурсивних дзвінках, тому я не міг робити обидва дзвінки однаково p, чи не так?
Мартін Ендер

@ m.buettner Можливо, ви можете використовувати Block, що коротше, ніж Module.
алефальфа

20

CFDG, 134 символи

Цей не зовсім дійсний, тому що ви не можете обмежити глибину рекурсії. Але проблема просто вимагає вирішення в цьому . :)

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5]t[trans 0 1 c(w) d(w)]t[trans c(w) d(w) 1 1]}

Результати виглядають приблизно так

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

Ще 46 символів (всього 180 символів ) можна навіть розфарбувати в:

startshape t
c(q)=cos(q/2)^2
d(q)=1+sin(q)/2
p=acos(-1)
shape t{w=rand(p)
SQUARE[x .5 .5 h 25 sat 1 b .2]t[trans 0 1 c(w) d(w) b .08 .8 h 2.2]t[trans c(w) d(w) 1 1 b .08 .8 h 2.2]}

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


Я знаю, що це не повністю онтопік, але як виглядатиме версія, якби замість "білого шуму" ви використовували "коричневий шум" як кути?
ɐɔıʇǝɥʇuʎs

@Synthetica ви маєте на увазі більше кутів біля 90 ° і менше при 0 і 180?
Мартін Ендер

@Synthetica Подібно до цього . Я не міг реалізувати фактичний шум у випадковому ході, тому що для цього потрібен вхідний параметр (останнє випадкове значення), коригування та передача його. Це зробило б граматику контекстно-чутливою, а тому CFDG не підтримується. Я трохи підробив це, просто натиснувши випадкові значення трохи більше на π / 2, використовуючи просту кубічну функцію на випадковому вибірці.
Мартін Ендер

Я думаю, що ваше посилання на imgur розірвано, а також, хоча я насолоджуюся кольором та формою, я думаю, що мені доведеться дискваліфікувати цю причину, яку ви згадали
Олександр-Бретт

@ ali0sha ви маєте рацію, ось фіксоване посилання . Дискваліфікація цього абсолютно справедлива, я просто хотів поділитися Context Free Art з деякими людьми, і це здавалося акуратним підходом до проблеми. ;) ... Ну, я все-таки отримав відповідь Mathematica ^^
Мартін Ендер

4

Постскрипт, 322 270

Редагувати: Здається, що realtimeне можна використовувати як належне насіння випадкових генераторів. Тому ми будемо використовувати змінну середовища для цієї мети і запустити програму так:

gs -c 20 $RANDOM -f tree.ps

або

gswin32c -c 20 %RANDOM% -f tree.ps

Зараз наші дерева менш передбачувані. До загальної кількості додано 14 байт. Інші зміни: 1) Аргумент програми передається в командному рядку. 2) Немає явного розміру лічильника ітерації для цієї мети (кут повороту лівої гілки зберігається в стеці, щоб потім намалювати праву гілку). 3) Немає іменної змінної для необхідної глибини - розмір стека є її зміщенням у стеці. Його залишають на виході, тобто його не споживають.

srand
250 99 translate
50 50 scale
/f{
    count
    dup index div dup 1 le{
        0 exch 0 setrgbcolor
        0 0 1 1 rectfill
        0 1 translate
        rand 5 mod 1 add 15 mul
        gsave
        dup rotate
        dup cos dup scale
        f
        grestore
        dup cos dup dup mul
        exch 2 index sin mul translate
        dup 90 sub rotate
        sin dup scale 1
        f
        pop
    }{pop}ifelse
}def
f

Я думаю, що це досить очевидно - стан графіки готується і fпроцедура викликається рекурсивно для кожного послідовного рівня глибини, двічі - для «лівої» та «правої» гілок. Робота з прямокутником1x1 розміру (див. Оригінальну шкалу) економить проблеми множення на бічну довжину. Кут повороту лівої гілки рандомізований - використовується один із 5 випадкових однаково розташованих поділів - я думаю, що це запобігає можливим потворним випадкам рівномірної випадковості.

Це може бути повільним при необхідній глибині більше 20 або більше.

Далі йде гольф-версія, використовуючи кодовані ASCII бінарні жетони (див. Відповідь luser droog з пов'язаної теми). Зверніть увагу, cos, sin, randне можуть використовувати ці позначення.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def srand 250 99<AD>$ 50 50<8B>$/f{count(8X68)$ 1 le{0(>)$ 0<9D>$ 0 0 1 1<80>$ 0 1<AD>$ rand 5 mod 1 add 15<~CecsG2u~>$ cos<388B>$ f(M8)$ cos(88l>)$ 2(X)$ sin<6CAD38>$ 90<A988>$ sin<388B>$ 1 f pop}{pop}(U)$}def f

.

/${{<920>dup 1 4 3 roll put cvx exec}forall}def
srand
250 99<AD>$
50 50<8B>$
/f{
count(8X68)$
1 le{
0(>)$ 0<9D>$
0 0 1 1<80>$
0 1<AD>$
rand 5 mod 1 add 15 
<~CecsG2u~>$
cos<388B>$ 
f
(M8)$
cos(88l>)$
2(X)$ sin<6CAD38>$
90<A988>$ sin<388B>$
1
f
pop
}{pop}(U)$
}def
f

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


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

@ ali0sha, -dGraphicsAlphaBits це прапор для виведення псевдоніму для запобігання нерівним краях великих квадратів, його можна опустити (або «приховати», наприклад, змінної середовища). Деяким людям може сподобатися більше без цього прапора (листя дерев отримують більшу "об'ємність"). Що ж, ці 20 байт не так вже й важливі. Я б сказав, що знижується 20-25%, використовуючи кодовані ascii двійкові маркери (судячи з відповіді на пов'язану тему). Можливо 50% знижка без ascii-кодування, 2 двійкові байти на маркер імені системи. Буде виглядати як деякі мови, які зазвичай перемагають;)
користувач2846289

Я думаю, ви повинні це зробити - зробіть це трохи більш конкурентоспроможним тут :)
alexander-brett

3

Coffeescript 377B 352B

Я відчуваю брудність написання coffeescript, але не можу знайти гідний пакет для малювання python3: - /

Q=(n)->X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=400;M=Math;T=[[175,400,50,i=0]];S=M.sin;C=M.cos;while [x,y,l,a]=T[i++]
 X.save();X.translate x,y;X.rotate -a;X.fillRect 0,-l,l,l;X.restore();T.push [e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2] if i<2**n

Javascript 393b 385b

Трохи красивіше в JavaScript, і я набагато щасливіший з циклом for-loop, але без синтаксису [x, y, z] = Я просто не можу зробити його досить коротким, щоб перемогти coffeescript

function Q(n){X=(D=document).body.appendChild(C=D.createElement('Canvas')).getContext('2d');C.width=C.height=600;M=Math;T=[[275,400,50,i=0]];while(A=T[i++]){X.save();X.translate(x=A[0],y=A[1]);X.rotate(-(a=A[3]));X.fillRect(0,-(l=A[2]),l,l);X.restore();S=M.sin;C=M.cos;i<M.pow(2,n)&&T.push([e=x-l*S(a),f=y-l*C(a),g=l*C(b=M.random()*M.PI/2),d=a+b],[e+g*C(d),f-g*S(d),l*S(b),d-M.PI/2])}}

Потрібно сказати, що я трохи прихильний, це майже вдвічі довше, ніж рішення математики: - / дивіться це в дії: http://jsfiddle.net/FK2NX/3/


Кілька пропозицій: Ви можете зберегти щонайменше 16 символів, використовуючи крапки з комою замість розривів рядків у CoffeeScript. В обох випадках, якщо якийсь із методів Xповернення X, ви можете їх зв'язати ланцюгом. І ви можете зберегти ще один непоганий набір символів, зберігаючи M.sinі M.cosв односимвольних змінних.
Мартін Ендер

На жаль, контекстні операції не повертають той контекст, який мене дуже засмутив. Крім того, ви можете перейменувати M.sin у Ms, але рядок Ms = M.sin займає більше символів, ніж економить ... Я погляну на викреслення пробілів.
Олександр-Бретт

Ні, ви можете просто зробити s=M.sin.
Мартін Ендер

Як я можу зробити S = ​​M.sin, але не R = X.ротати?
Олександр-Бретт

Я гадаю, rotateвикористовує this, а sinні. Вам потрібно було б зробити щось на кшталт R=X.rotate.bind(X), але, мабуть, цього вже не варто.
Мартін Ендер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.