Vẽ một bông tuyết


18

Joe sống ở Bahamas. Đó là mùa đông. Các con anh thất vọng vì không có tuyết. Joe cần phải làm tuyết cho trẻ em của mình. May mắn thay, anh ta có một máy in 3-d. Anh dự định làm những bông tuyết với nó. Thật không may, anh ta không biết một bông tuyết sẽ trông như thế nào. Trong thực tế, anh chưa bao giờ nhìn thấy một bông tuyết! Hãy để chúng tôi giúp anh ấy bằng cách tạo ra một chương trình tự động tạo ra hình ảnh 2d của một bông tuyết cho anh ấy.

Đầu vào

Đường kính của hình ảnh (tính bằng pixel), tỷ lệ phần trăm của hình ảnh thực sự là một bông tuyết.

Đầu ra

Một hình ảnh của một bông tuyết với đường kính yêu cầu. Nó có thể được lưu vào một tập tin hoặc hiển thị cho người dùng.

Thông số kỹ thuật

Tạo một cái nêm có góc 30 độ. Tạo một cây Brownian với hạt giống ban đầu tại điểm của nêm. Phản chiếu hình nêm xung quanh trung tâm của hình ảnh 12 lần để tạo phần còn lại của hình ảnh. Bông tuyết có màu Trắng. Nền có màu Đen.

Chấm điểm

Do thực tế có nhiều cách khác nhau để tạo Cây Brownian, điểm số là 10 * số lần nâng cấp - điểm golf.

Điểm golf được định nghĩa là số byte trong chương trình với các phần thưởng sau:

-20% Có thể tùy ý chỉ định tính đối xứng của bông tuyết.

-50% Có thể chỉ định hình dạng của bông tuyết. (Bằng cách có thể chỉ định tỷ lệ độ dài của các cạnh của nêm.)

Điểm số cao nhất chiến thắng.

Dưới đây là hình ảnh hình dạng của cái nêm sẽ có tỷ lệ xấp xỉ 2:

Nêm

Bảng điểm:

Martin Mông Cổ: 10 * 14 - 409 = -269

Nimi: 10 * 1 - 733 * .5 = -356.5

Trình tối ưu hóa: 10 * 5 - 648 = -598

Người chiến thắng là Martin với số điểm -269!



9
Tôi không thể hiểu tại sao, nếu chúng tôi bị cáo buộc giúp đỡ một người chưa bao giờ nhìn thấy bông tuyết biết họ trông như thế nào, chúng tôi phải làm cho họ có sự đối xứng xoay vòng của trật tự 4. Chúng tôi có nên troll anh chàng tội nghiệp không?
Peter Taylor

1
@Conor "Điểm số là 10 * số lần nâng cấp - sân golf." Chương trình đó sẽ có số điểm -300000000. Đó là rất thấp.
TheNumberOne

1
Nêm 6x60deg! một cải tiến về những gì nó đã nói tại thời điểm nhận xét của @PeterTaylor, nhưng thực sự bạn cần nêm 12x30deg .. 6 cho phía bên phải của mỗi 6 điểm và 6 điểm phản ánh cho phía bên trái của mỗi điểm. BTW, tôi không hiểu phần thưởng thứ hai
Level River St

2
@Optimizer Xong, nên rõ ràng hơn bây giờ.
TheNumberOne

Câu trả lời:


16

Toán học, 409 byte

{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]

Ung dung:

{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
 ]

Điều này dự kiến ​​nhập vào dạng {n,p}nkích thước hình ảnh bằng pixel và plà tỷ lệ phần trăm của hình ảnh được bao phủ bởi bông tuyết.

Phải mất một nửa phút để tạo ra một bông tuyết với các tham số đã cho. Bạn có thể tăng tốc nó bằng cách thay đổi giá trị mtừ 999đến 99, nhưng sau đó kết quả có vẻ hơi thưa thớt. Tương tự như vậy, bạn có thể tăng chất lượng bằng cách sử dụng số lượng lớn hơn, nhưng sau đó sẽ mất rất nhiều thời gian.

Tôi đang tạo cây Brownian trên một mạng số nguyên, đặt các hạt mới vào {999, 0}và di chuyển ngẫu nhiên sang trái và lên hoặc xuống (không phải bên phải), cho đến khi chúng chạm vào các hạt hiện có. Tôi cũng hạn chế chuyển động đến nêm trong khoảng từ 0 đến 30 độ. Cuối cùng, tôi phản ánh cái nêm đó trên trục x và hiển thị nó với 5 góc quay của nó.

Dưới đây là một số kết quả (nhấp vào phiên bản lớn hơn):

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Và đây là hai hình ảnh động của cây Brownian đang phát triển (10 hạt trên mỗi nêm trên mỗi khung):

nhập mô tả hình ảnh ở đâynhập mô tả hình ảnh ở đây


2
Wow tôi thích ... tất cả chúng, thực sự. Kết quả thật tuyệt!
Sp3000

6

JavaScript, ES6, 799 740 695 658 648

Tôi chỉ đếm hai thẻ canvas và hàm ftừ đoạn trích dưới đây như là một phần của số byte. Phần còn lại của các công cụ là cho bản demo trực tiếp

Để xem nó hoạt động, chỉ cần chạy đoạn trích dưới đây trong Firefox mới nhất cho kích thước và tỷ lệ thông qua các hộp đầu vào

Lưu ý rằng bạn sẽ phải ẩn kết quả sau đó hiển thị lại trước khi một bông tuyết liên tiếp

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>

Dưới đây là một vài ví dụ ám chỉ với kích thước và tỷ lệ phần trăm khác nhau. Cái tốt nhất được gọi là SkullFlake (đầu tiên trong danh sách). Nhấp vào hình ảnh để xem chúng ở độ phân giải đầy đủ.

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Rất nhiều sự giúp đỡ và đầu vào từ Martin và githubphagocyte.


Điều này không lấy phần trăm hình ảnh được điền làm đầu vào.
TheNumberOne

@TheBestOne phải mất phần trăm vào tài khoản ngay bây giờ. Xin lưu ý rằng vì đây là một bông tuyết dựa trên cây Brown, nên tỷ lệ phần trăm cũng như tỷ lệ cho chiều dài nêm không thể chính xác vì vai trò của sự ngẫu nhiên đang diễn ra.
Tối ưu hóa

Điều này đủ điều kiện ngay bây giờ.
TheNumberOne

1

Haskell, 781 733 byte

Chương trình có tính năng „chỉ định tỷ lệ độ dài của các cạnh của tùy chọn nêm, do đó bạn phải gọi nó bằng ba đối số dòng lệnh:

./sf 150 50 40

Đối số # 1 là kích thước của hình ảnh, # 2 %% pixel trong hình nêm và # 3 chiều dài (tính bằng%) của cạnh ngắn hơn của hình nêm. Hình ảnh được lưu trong một tệp có tên „o.png.

150-50-40: 150-50-40

Chương trình của tôi tạo ra những bông tuyết với các gai bị cắt, bởi vì các pixel mới bắt đầu trên trục giữa của nêm (chấm màu xanh lá cây, xem bên dưới) và có xu hướng ở đó, vì chúng di chuyển ngẫu nhiên sang trái, lên hoặc xuống. Khi các pixel bên ngoài nêm bị loại bỏ, các đường thẳng xuất hiện trên ranh giới của nêm (mũi tên màu xanh lá cây). Tôi đã quá lười biếng để thử các đường dẫn khác cho các pixel.

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

Khi nêm đủ lớn (đối số thứ 3 100), các gai trên trục giữa có thể phát triển và sau đó có 12 cái.

150-40-100: 150-40-100

Vài pixel tạo hình tròn (trái: 150-5-20; phải 150-20-90).

150-5-20 150-20-90

Chương trình:

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: mũi nhọn nằm trên trục giữa của nêm. Nêm đi lên và xuống 15 độ theo trục x. Trong một *-*-100hình ảnh, cả hai mặt của nó đều chạm tới viền trái của hình ảnh (xem hình ảnh thứ hai để biết vị trí của hình nêm). Có các pixel ở khoảng một nửa các cạnh - các nửa còn lại trống.
nimi

1
Sử dụng bộ đếm này chương trình của bạn có độ dài 841 byte.
TheNumberOne

@TheBestOne: Tab so với Spaces khi thụt lề. Tôi đã trộn chúng lên khi thêm 4 khoảng trắng cho code style. Tôi đã chỉnh sửa bài đăng của mình và đặt Tab, nhưng chúng vẫn xuất hiện dưới dạng khoảng trắng. Có ai biết làm thế nào để khắc phục nó?
nimi

@nimi Trên trang web TheBestOne được liên kết có một #liên kết băm nhỏ mà bạn có thể nhấp vào. Bạn có thể dán mã thẻ của bạn ở đó và liên kết nó.
Sp3000

Bạn có thể có thể tạo một liên kết đến mã ở đâu đó. Bạn có thể sử dụng khoảng trắng thay vì các tab để thụt lề. Bạn có thể nhận thủ công bằng code stylecách thụt lề mỗi dòng 4 khoảng trắng.
TheNumberOne

0

Xử lý 2 - 575 ký tự

Đưa vào một tệp f có dòng đầu tiên là kích thước hình ảnh và dòng thứ hai là bán kính mảnh. Mỗi lần đặt một điểm mới, nó sẽ được xoay quanh tâm 12 lần. Điều này tạo ra một hiệu ứng rất giống như một cái nêm xoay, nhưng không hoàn toàn giống nhau.

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

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

bạn có thể xử lý ở đây


3
Điều này không hoàn toàn phù hợp với các thông số kỹ thuật. Điều này sẽ đủ điều kiện nếu bạn phản ánh điểm xung quanh trung tâm thay vì xoay nó.
TheNumberOne

color(255)có thể trở thành color(-1)để tiết kiệm một byte
Kritixi Lithos
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.