눈송이 그리기


18

조는 바하마에 산다. 겨울입니다. 그의 아이들은 눈이없는 것에 실망했습니다. 조는 아이들을 위해 눈을 만들어야합니다. 다행히도 그는 3 차원 프린터를 가지고 있습니다. 그는 그것으로 눈송이를 만들 계획입니다. 불행히도 그는 눈송이가 어떻게 생겼는지 전혀 모른다. 실제로, 그는 눈송이를 본 적이 없다! 그를 위해 눈송이의 2D 이미지를 자동으로 생성하는 프로그램을 만들어 그를 도와주십시오.

입력

실제로 눈송이 인 이미지의 백분율 (픽셀 단위)입니다.

산출

필요한 직경의 눈송이 이미지. 파일로 저장하거나 사용자에게 표시 할 수 있습니다.

명세서

30도 각도의 웨지를 만듭니다. 웨지 지점에 초기 시드가 있는 Brownian Tree 를 만듭니다 . 이미지 중앙 주위의 쐐기를 12 회 반사하여 나머지 이미지를 생성합니다. 눈송이의 색상은 흰색입니다. 배경은 검은 색입니다.

채점

Brownian Tree를 생성하는 다른 방법이 있기 때문에 점수는 10 * 업 보이트 수-골프 점수입니다.

골프 점수는 다음 보너스와 함께 프로그램의 바이트 수로 정의됩니다.

-20 % 눈송이의 대칭을 임의로 지정할 수 있습니다.

-50 % 눈송이 모양을 지정할 수 있습니다. (쐐기의 측면 길이의 비율을 지정할 수 있음)

최고 점수가 이깁니다.

다음은 웨지의 모양이 약 2의 비율 인 그림입니다.

쐐기

스코어 보드 :

마틴 버트 너 : 10 * 14-409 = -269

니미 : 10 * 1-733 * .5 = -356.5

옵티 마이저 : 10 * 5-648 = -598

승자는 점수 -269 인 마틴입니다!



9
눈송이를 본 적이없는 사람이 자신의 모습을 알도록 돕는다 고해서 왜 4의 회전 대칭을 갖도록해야하는지 이해할 수 없습니다. 우리는 가난한 사람을 트롤링해야합니까?
피터 테일러

1
@Conor "점수는 10 * 업 보이트 수-golfscore입니다." 이 프로그램의 점수는 -300000000입니다. 매우 낮습니다.
TheNumberOne

1
6x60deg 웨지! @PeterTaylor의 의견 당시에 말한 내용에 대한 개선 사항이지만 실제로 12x30deg 웨지가 필요합니다. 각 6 포인트의 오른쪽에 6, 각 포인트의 왼쪽에 6을 반영합니다. BTW, 나는 두 번째 보너스 이해하지 않는다
레벨 강 세인트

2
@Optimizer 완료, 이제 더 명확해야합니다.
TheNumberOne

답변:


16

Mathematica, 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}np

주어진 매개 변수로 눈송이를 생성하는 데 30 분 정도 걸립니다. 당신의 값을 변경하여 속도를 높일 수 있습니다 m에서 99999,하지만 결과는 비트 스파 스 보인다. 마찬가지로 더 큰 숫자를 사용하여 품질을 높일 수 있지만 시간이 오래 걸립니다.

정수 격자에 브라운 트리를 형성하고에 새 입자를 배치 {999, 0}하고 기존 입자에 부딪 칠 때까지 무작위로 왼쪽과 위 또는 아래로 (오른쪽이 아닌) 무작위로 이동합니다. 또한 모션을 0도에서 30도 사이의 쐐기로 제한합니다. 마지막으로, 그 쐐기를 x 축에 반영하고 5 회전으로 표시합니다.

결과는 다음과 같습니다 (더 큰 버전을 보려면 클릭).

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

그리고 다음은 Brownian 나무가 자라는 두 가지 애니메이션입니다 (프레임 당 웨지 당 10 개의 입자).

여기에 이미지 설명을 입력하십시오여기에 이미지 설명을 입력하십시오


2
와우 .. 실은 다 좋아. 결과는 좋습니다!
Sp3000

6

자바 스크립트, 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 (목록의 첫 번째)입니다. 이미지를 클릭하면 전체 해상도로 볼 수 있습니다.

여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오 여기에 이미지 설명을 입력하십시오

Martin과 githubphagocyte의 많은 도움과 의견.


입력으로 채워지는 이미지의 백분율을 차지하지 않습니다.
TheNumberOne

@TheBestOne 그것은 지금 비율을 고려합니다. 이것은 브라운 트리 기반의 눈송이이기 때문에 임의의 역할이 작용하기 때문에 쐐기 길이의 비율이나 비율이 정확하지 않을 수 있습니다.
Optimizer

이것은 지금 자격이 있습니다.
TheNumberOne

1

하스켈, 781 733 바이트

이 프로그램에는 "쐐기의 변의 길이 비율 지정"옵션이 있으므로 세 가지 명령 줄 인수로 호출해야합니다.

./sf 150 50 40

인수 # 1은 이미지의 크기, # 2 쐐기의 픽셀 %, # 3 쐐기의 짧은면의 길이 (%)입니다. 이미지는 "o.png"라는 파일에 저장됩니다.

150-50-40 : 150-50-40

내 프로그램은 새 픽셀이 쐐기의 중간 축 (녹색 점, 아래 참조)에서 시작하고 왼쪽, 위 또는 아래로 똑같이 무작위로 이동하기 때문에 거기에 머물러 있기 때문에 컷 스파이크가있는 눈송이를 생성합니다. 쐐기 외부의 픽셀이 삭제되면 쐐기의 경계에 직선이 나타납니다 (녹색 화살표). 픽셀에 대한 다른 경로를 시도하기에는 너무 게으르다.

150-50-40 : 150-40-40e

쐐기가 충분히 크면 (제 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

@Optimizer : 스파이크가 쐐기의 가운데 축에 있습니다. 쐐기는 x 축으로 15도 위 아래로 이동합니다. 안에*-*-100 그것의 양쪽 모두에 화상의 왼쪽 경계에 도달 화상 (웨지의 위치에 대한 두 번째 이미지 참조). 측면의 대략 절반에 픽셀이 있습니다. 다른 절반은 비어 있습니다.
nimi

1
이 카운터를 사용 하면 프로그램 길이가 841 바이트입니다.
TheNumberOne

@TheBestOne : 들여 쓰기시 탭 대 공백. 에 공백을 4 개 더 추가 할 때 혼합했습니다 code style. 게시물을 수정하고 탭을 설정했지만 여전히 공백으로 나타납니다. 누구든지 고치는 법을 알고 있습니까?
nimi

@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)1 바이트를 절약 할 수 있습니다
Kritixi Lithos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.