Намалюйте Сніжинку


18

Джо живе на Багамах. Це зима. Його діти розчаровані, що снігу немає. Джо потрібно зробити сніг для своїх дітей. На щастя, у нього 3-д принтер. Він планує зробити з неї сніжинки. На жаль, він поняття не має, як виглядатиме сніжинка. Насправді він ніколи не бачив сніжинки! Допоможемо йому, створивши програму, яка автоматично генерує для нього 2d-зображення сніжинки.

Вхідні дані

Діаметр зображення (у пікселях), відсоток зображення, який фактично є сніжинками.

Вихід

Зображення сніжинки з необхідним діаметром. Він може бути збережений у файл або відображений користувачеві.

Технічні умови

Створіть клин, який має кут 30 градусів. Створіть броунівське дерево з початковим насінням у точці клина. Відбийте клин навколо центру зображення 12 разів, щоб генерувати решту зображення. Сніжинка має колір Білий. Фон має колір Чорний.

Оцінка балів

У зв'язку з тим, що існує різні способи генерування броунівського дерева, оцінка складає 10 * кількість відгуків - оцінка гольфу.

Оцінка гольфу визначається як кількість байтів у програмі з такими бонусами:

-20% Може довільно задати симетрію сніжинки.

-50% Може вказати форму сніжинки. (Вміючи визначати співвідношення довжин сторін клину.)

Найвищий результат виграє.

Ось малюнок, якою була б форма клина при співвідношенні приблизно 2:

Клин

Табло:

Мартін Бутнер: 10 * 14 - 409 = -269

Німі: 10 * 1 - 733 * .5 = -356.5

Оптимізатор: 10 * 5 - 648 = -598

Переможець - Мартін з рахунком -269!



9
Я не можу зрозуміти, чому, якщо ми нібито допомагаємо комусь, хто ніколи не бачив сніжинки, знати, як вони виглядають, ми повинні зробити їх ротаційною симетрією порядку 4. Чи треба нам обходити бідного хлопця?
Пітер Тейлор

1
@Conor "Оцінка 10 * кількість нагород - гольфскор." Ця програма мала б оцінку -300000000. Це дуже низько.
TheNumberOne

1
6x60deg клини! поліпшення того, що було сказано під час коментаря @PeterTaylor, але насправді вам потрібні клини 12x30deg .. 6 для правої частини кожної з 6 точок, і 6 відбитих для лівої частини кожної точки. До речі, я не розумію другого бонусу
Level River St

2
@Optimizer Готово, зараз має бути зрозуміліше.
TheNumberOne

Відповіді:


16

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

{n,p}=Input[];m=999;Clear@f;_~f~_=0;0~f~0=1;r=RandomInteger;For[i=0,i<m,++i,For[x=m;y=0,f[x+1,y]+f[x-1,y]+f[x,y+1]+f[x,y-1]<1,a=b=-m;While[x+a<0||y+b<0||(y+b)/(x+a)>Tan[Pi/6],a=-r@1;b=r@2-1];x+=a;y+=b];x~f~y=1];Graphics[{White,g=Point/@Join@@{c=Cases[Join@@Table[{i,j}-1,{i,m},{j,m}],{i_,j_}/;i~f~j>0],c.{{1,0},{0,-1}}},Array[Rotate[g,Pi#/3,{0,0}]&,6]},Background->Black,ImageSize->n*p,ImageMargins->n(1-p)/2]

Безголівки:

{n,p}=Input[];
m = 999;
ClearAll@f;
_~f~_ = 0;
0~f~0 = 1;
r = RandomInteger;
For[i = 0, i < m, ++i,
  For[x = m; y = 0, 
   f[x + 1, y] + f[x - 1, y] + f[x, y + 1] + f[x, y - 1] < 1,
   a = b = -m;
   While[x + a < 0 || y + b < 0 || (y + b)/(x + a) > Tan[Pi/6],
    a = -r@1;
    b = r@2 - 1
    ];
   x += a;
   y += b
   ];
  x~f~y = 1
  ];
Graphics[
 {White, g = 
   Point /@ 
    Join @@ {c = 
       Cases[Join @@ Table[{i, j} - 1, {i, m}, {j, m}], {i_, j_} /;
          i~f~j > 0], c.{{1, 0}, {0, -1}}}, 
  Array[Rotate[g, Pi #/3, {0, 0}] &, 6]},
 Background -> Black,
 ImageSize -> n*p,
 ImageMargins -> n (1 - p)/2
 ]

Це очікує введення форми, {n,p}де nрозмір зображення в пікселях, і pстановить відсоток зображення, який повинен охоплювати сніжинка.

Щоб генерувати сніжинку із заданими параметрами, потрібно щось на півхвилини. Ви можете пришвидшити його, змінивши значення mз 999на 99, але результат виглядає дещо рідким. Так само ви можете підвищити якість, використовуючи більші цифри, але тоді це займе дуже багато часу.

Я формую броунівське дерево з цілої решітки, розміщую нові частинки на {999, 0}, і переміщаю випадковим чином вліво і вгору або вниз (не вправо), поки вони не потраплять на існуючі частинки. Я також обмежую рух до клину від 0 до 30 градусів. Нарешті, я відображаю цей клин на осі x і відображаю його за допомогою 5 обертів.

Ось деякі результати (натисніть для більшої версії):

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

Ось дві анімації броунського дерева (10 частинок на клин на кадр):

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


2
Нічого мені не подобається ... насправді. Результати приємні!
Sp3000

6

JavaScript, ES6, 799 740 695 658 648

Я підраховую лише два теги полотна та функцію fз фрагмента нижче, як частина підрахунку байтів. Залишок речей - для демонстрації в прямому ефірі

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

Зауважте, що вам доведеться приховати результат, а потім показати ще раз перед поспіль снігом

f=(N,P)=>{E.width=E.height=D.width=D.height=N
E.style.background="#000"
C=D.getContext("2d"),F=E.getContext("2d")
C.strokeStyle='#fff'
M=Math,r=M.random,I=0,n=N/2
C.beginPath()
C.rect(n,n,2,2)
C.fill()
B=_=>{x=n*P/100,y=0,w=[]
do{w.push([x,y])
do{X=2*((r()*2)|0)
Y=2*(((r()*3)|0)-1)
}while(x-X<0||y-Y<0||(y-Y)/(x-X)>.577)
x-=X,y-=Y}while(!C.isPointInPath(n+x,n+y))
I++
w=w.slice(-4)
x=w[0]
C.moveTo(x[0]+n,x[1]+n)
w.map(x=>C.lineTo(n+x[0],n+x[1]))
C.stroke()
E.width=E.height=N
for(i=0;i<12;i++){F.translate(n,n)
i||F.rotate(M.PI/6)
i-6?F.rotate(M.PI/3):F.scale(1,-1)
F.translate(-n,-n)
F.drawImage(D,0,0)}
I<(n*n*P*.22/100)&&setTimeout(B,15)}
B()}
<input placeholder="Input N" id=X /><input placeholder="Input percentage" id=Y /><button onclick="f(~~X.value,~~Y.value)">Create snowflake</button><br>
<canvas id=E><canvas id=D>

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

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

Велика допомога та вклад від Мартіна та гітубфагоцитів.


При цьому відсоток зображення, яке заповнюється, не приймається як вхідне.
TheNumberOne

@TheBestOne зараз враховує відсоток. Зауважте, що оскільки це сніжинка на основі броунівського дерева, ані відсоток, ані відношення до довжини клина не можуть бути точними, оскільки грає випадковість.
Оптимізатор

Це кваліфікується зараз.
TheNumberOne

1

Haskell, 781 733 байт

У програмі є опція „визначити співвідношення довжин сторін клина“, тому вам доведеться називати її трьома аргументами командного рядка:

./sf 150 50 40

Аргумент №1 - це розмір зображення, №2% пікселів у клині та №3 - довжина (у%) коротшої сторони клина. Зображення зберігається у файлі під назвою „o.png“.

150-50-40: 150-50-40

Моя програма створює сніжинки із відрізаними шипами, оскільки нові пікселі починаються на середній осі клина (зелена крапка, див. Нижче) і, як правило, залишаються там, оскільки вони рухаються однаково випадково вліво, вгору чи вниз. Коли пікселі поза клином відкидаються, на межі клина з’являються прямі лінії (зелена стрілка). Я був лінивий, щоб спробувати інші шляхи для пікселів.

150-50-40: 150-40-40е

Коли клин досить великий (3-й аргумент 100), шипи на середній осі можуть зростати, і тоді їх є 12.

150-40-100: 150-40-100

Мало пікселів мають круглі форми (зліва: 150-5-20; праворуч 150-20-90).

150-5-20 150-20-90

Програма:

import System.Environment;import System.Random;import Graphics.GD
d=round;e=fromIntegral;h=concatMap;q=0.2588
j a(x,y)=[(x,y),(d$c*e x-s*e y,d$s*e x+c*e y)] where c=cos$pi/a;s=sin$pi/a
go s f w p@(x,y)((m,n):o)|x<1=go s f w(s,0)o|abs(e$y+n)>q*e x=go s f w p o|elem(x-m,y+n)f&&(v*z-z)*(b-q*z)-(-v*q*z-q*z)*(a-z)<0=p:go s(p:f)w(s,0)o|1<2=go s f w(x-m,y+n)o where z=e s;a=e x;b=e y;v=e w/100
main = do 
 k<-getArgs;g<-getStdGen;let(s:p:w:_)=map read k
 i<-newImage(2*s,2*s);let t=h(j 3)$h(\(x,y)->[(x,y),(d$0.866*e x+0.5*e y,d$0.5*e x-0.866*e y)])$take(s*d(q*e s)*p`div`100)$go s[(0,0)]w(s,0)$map(\r->((1+r)`mod`2,r))(randomRs(-1,1)g)
 mapM(\(x,y)->setPixel(x+s,y+s)(rgb 255 255 255)i)((h(j(-3/2))t)++(h(j(3/2))t));savePngFile "o.png" i

@ Оптимізатор: шип знаходиться на середній осі клина. Клин йде вгору і вниз на 15 градусів до осі x. У *-*-100зображенні обидві його сторони доходять до лівої межі зображення (див. Друге зображення для положення клину). Приблизно на половині боків є пікселі - інші половинки порожні.
німі

1
Використовуючи цей лічильник, ваша програма має довжину 841 байт.
TheNumberOne

@TheBestOne: вкладки проти пробілів під час відступу. Я змішав їх, додаючи додаткові 4 пробіли для code style. Я відредагував свою публікацію та встановив вкладки, але вони все ще відображаються як пробіли. Хтось знає, як це виправити?
німі

@nimi На веб-сайті TheBestOne є невелике хеш- #посилання, на яке можна натиснути. Ви можете вставити туди свій вкладений код і пов’язати його.
Sp3000

Можливо, ви могли б десь зробити посилання на код. Ви можете використовувати пробіли замість вкладок для відступу. Ви могли отримати вручну code style, відступаючи пробіли кожного рядка 4.
TheNumberOne

0

Обробка 2 - 575 символів

Бере у файл f, перший рядок якого є розміром зображення, а другий - радіусом пластівців. Кожен раз, коли розміщується нова точка, вона обертається навколо центру 12 разів. Це створює дуже схожий ефект, як обертовий клин, але не зовсім однаковий.

  int d,w,h,k,l,o,p,x,y;
  String n[] = loadStrings("f.txt");
  d=Integer.parseInt(n[0]);
  h=Integer.parseInt(n[1]);
  size(d,d);
  w=d/2;
  k=l=(int)random(d); 
  background(0);
  loadPixels();
  o=p=0;
  pixels[w*w*2+w]=color(255);
  while(true)
  {
    o=k+(int)random(-2,2);
    p=l+(int)random(-2,2);
    if(p*d+o>d*d-1 || p*d+o<0 || o<0 || o>d){
      k=l=(int)random(d);
    }
    else
    {
      if(pixels[p*d+o]==color(255))
      {
        p=l-w;
        o=k-w;
        if(o*o+p*p>h*h){break;}
        float s,c;
        for(int j=0;j<12;j++)
        {
          s=sin(PI*j/6);
          c=cos(PI*j/6);         
          x=(int)((o*c)-(p*s));
          y=(int)(((p*c)+(o*s)));
          pixels[(int)(d*y+x+w+(w*d))]=color(255);
        }
        k=l=(int)random(d);  
      }
      else
      {
        k=o;
        l=p;
      }
    }
  }
  updatePixels(); 

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

ви можете отримати тут обробку


3
Це не зовсім відповідає технічним умовам. Це може бути кваліфіковано, якщо ви відбивали точку навколо центру, а не обертати її.
TheNumberOne

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