Bir kar tanesi çizin


18

Joe Bahamalar'da yaşıyor. Bu kıştır. Çocukları kar olmadığı için hayal kırıklığına uğruyor. Joe'nun çocukları için kar yapması gerekiyor. Neyse ki, 3 boyutlu bir yazıcısı var. Onunla kar taneleri yapmayı planlıyor. Ne yazık ki bir kar tanesinin nasıl görüneceği hakkında hiçbir fikri yok. Aslında, hiç bir kar tanesi görmedi! Otomatik olarak onun için bir kar tanesi 2d görüntüsü üreten bir program oluşturarak ona yardımcı olalım.

Giriş

Görüntünün çapı (piksel cinsinden), aslında bir kar tanesi olan görüntünün yüzdesi.

Çıktı

Gerekli çapa sahip bir kar tanesi görüntüsü. Bir dosyaya kaydedilebilir veya kullanıcıya gösterilebilir.

Özellikler

30 derecelik bir açıya sahip bir kama oluşturun. Kama noktasında başlangıç ​​tohumu ile bir Brownian Ağacı oluşturun . Görüntünün geri kalanını oluşturmak için kama görüntünün merkezi etrafında 12 kez yansıtın. Kar tanesi Beyaz renktedir. Arka plan Siyah renktedir.

puanlama

Bir Brownian Ağacı oluşturmak için farklı yollar olduğundan, skor 10 * upvotes - golf skoru sayısıdır.

Golf puanı, aşağıdaki bonuslarla programdaki bayt sayısı olarak tanımlanır:

-20% Kartanenin simetrisini keyfi olarak belirleyebilir.

-50% Kar tanesinin şeklini belirtebilir. (Kamanın yanlarının uzunluklarının oranını belirleyebilmek.)

En yüksek puan kazanır.

İşte kama şeklinin yaklaşık 2 oranı ile bir resim:

kama

scoreboard:

Martin Buttner: 10 * 14-409 = -269

Nimi: 10 * 1-733 * .5 = -356,5

Doktor: 10 * 5 - 648 = -598

Kazanan Martin -269 puanla!



9
Neden bir kar tanesi görmemiş birine nasıl göründüklerini bilmelerine yardım edersek, neden 4'ün dönme simetrisine sahip olmaları gerektiğine inanamıyorum. Fakir adamı trol ediyor muyuz?
Peter Taylor

1
@Conor "Skor 10 * upvotes sayısı - golfscore." Bu programın puanı -300000000 olurdu. Bu çok düşük.
TheNumberOne

1
6x60 derece takozlar! @PeterTaylor'ın yorumu sırasında söyledikleri üzerinde bir gelişme, ancak aslında 12x30deg kamalara ihtiyacınız var .. 6 noktanın her birinin sağ tarafı için 6 ve her noktanın sol tarafı için 6 yansıyan kama. BTW, ikinci bonusu anlamıyorum
Level River St

2
@Optimizer Done, şimdi daha net olmalı.
TheNumberOne

Yanıtlar:


16

Mathematica, 409 bayt

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

Ungolfed:

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

Bu şekilde giriş bekler resmin piksel boyutu ve kar tanesi tarafından karşılanması gereken resmin yüzdesidir.{n,p}np

Verilen parametrelerle bir kar tanesi oluşturmak yarım dakika gibi bir şey alır. Sen değerini değiştirerek hızlandırabilir mgelen 999etmek 99, ancak daha sonra sonuç biraz seyrek görünüyor. Aynı şekilde, daha büyük sayılar kullanarak kaliteyi yükseltebilirsiniz, ancak o zaman çok uzun sürer.

Brownian ağacını bir tamsayı kafes üzerinde oluşturuyorum, yeni parçacıkları yerleştiriyorum ve mevcut parçacıklara {999, 0}çarpana kadar rastgele sola ve yukarı veya aşağı (sağa değil) hareket ediyorum . Ayrıca hareketi kama ile 0 ila 30 derece arasında kısıtlıyorum. Sonunda, bu kamayı x ekseni üzerinde yansıtıyorum ve 5 rotasyonu ile sergiliyorum.

İşte bazı sonuçlar (daha büyük versiyon için tıklayınız):

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

Ve burada Brownian ağacının büyüyen iki animasyonu (çerçeve başına kama başına 10 parçacık):

resim açıklamasını buraya girinresim açıklamasını buraya girin


2
Vay be ... hepsini seviyorum, aslında. Sonuçlar güzel!
Sp3000

6

JavaScript, ES6, 799 740 695 658 648

Yalnızca iki tuval etiketini ve fbayt sayımının bir parçası olarak aşağıdaki snippet'ten işlevi sayıyorum. Geri kalan şeyler canlı demo içindir

Eylem halinde izlemek için, aşağıdaki snippet'i giriş kutuları aracılığıyla boyut ve oran veren en son Firefox'ta çalıştırın

Sonucu gizlemeniz ve ardışık bir kar tanesinden önce tekrar göstermeniz gerekeceğini unutmayın

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>

Aşağıda, farklı boyut ve yüzdelere sahip birkaç örnek oluşturma bulunmaktadır. En iyisi SkullFlake (listede ilk sırada) olarak adlandırılır. Tam çözünürlükte görmek için resimlere tıklayın.

resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin resim açıklamasını buraya girin

Martin ve githubphagocte'den çok yardım ve girdi.


Bu girdi olarak doldurulmuş görüntünün yüzdesini almaz.
TheNumberOne

@TheBestOne şimdi yüzdeyi dikkate alıyor. Bu bir Brownian ağacı bazlı kar tanesi olduğu için, rasgele bir rol oynadığından kama uzunluklarının yüzdesinin veya oranının doğru olamayacağını unutmayın.
Doktor

Bu şimdi geçerli.
TheNumberOne

1

Haskell, 781 733 Bayt

Programda „kama kenarlarının uzunluklarının oranını belirtin“ seçeneği bulunmaktadır, bu nedenle üç komut satırı argümanı ile çağırmanız gerekir:

./sf 150 50 40

Bağımsız değişken # 1 görüntünün boyutudur, # 2 kamadaki piksellerin% 'si ve # 3 kamanın daha kısa tarafının uzunluğudur (% olarak). Görüntü „o.png“ adlı bir dosyaya kaydedilir.

150-50-40: 150-50-40

Benim programım kesik dikenli kar taneleri üretir, çünkü yeni pikseller kamanın orta ekseninde başlar (yeşil nokta, aşağıya bakın) ve eşit olarak rastgele sola, yukarı veya aşağı hareket ettikleri için orada kalma eğilimindedirler. Kamanın dışındaki pikseller atılırken, kamanın sınırında düz çizgiler görünür (yeşil ok). Pikseller için diğer yolları denemek için çok tembeltim.

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

Kama yeterince büyük olduğunda (3. argüman 100) orta eksendeki sivri uçlar büyüyebilir ve 12 tanesi vardır.

150-40-100: 150-40-100

Birkaç piksel yuvarlak şekiller oluşturur (sol: 150-5-20; sağ 150-20-90).

150-5-20 150-20-90

Program:

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: Başak, kamanın orta eksenindedir. Kama x eksenine 15 derece yukarı ve aşağı gider. Bir *-*-100görüntüde her iki tarafı da görüntünün sol kenarına ulaşır (kama konumu için ikinci görüntüye bakın). Kenarların yaklaşık yarısında pikseller var - diğer yarılar boş.
nimi

1
Bu sayacı kullanarak programınızın uzunluğu 841 bayttır.
TheNumberOne

@TheBestOne: Girintileme sırasında Sekmeler ve Boşluklar. Ben ek 4 boşluk eklerken onları karıştırdım code style. Yazımı düzenledim ve Sekmeler ayarladım, ancak yine de boşluk olarak görünüyorlar. Bunu nasıl düzeltebileceğini bilen var mı?
nimi

@nimi TheBestOne bağlantılı sitede tıklayabileceğiniz küçük bir karma #bağlantı var. Sekmeli kodunuzu oraya yapıştırabilir ve bağlayabilirsiniz.
Sp3000

Muhtemelen bir yerlerde koda bir bağlantı yapabilirsiniz. Girintilemek için sekmeler yerine boşluk kullanabilirsiniz. code styleHer satır 4 boşluğunu girintili olarak manuel olarak elde edebilirsiniz .
TheNumberOne

0

2 - 575 karakter işleniyor

İlk satırı görüntü boyutu, ikincisi pul yarıçapı olan bir dosyayı alır. Her yeni nokta yerleştirildiğinde merkez etrafında 12 kez döndürülür. Bu, döndürülmüş bir kama ile çok benzer bir etki yaratır, ancak tam olarak aynı değildir.

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

resim açıklamasını buraya girin resim açıklamasını buraya girin

Eğer işleme alabilirsiniz burada


3
Bu özelliklere tam olarak uymuyor. Merkezi döndürmek yerine noktayı yansıtıyorsanız, bu hak kazanacaktır.
TheNumberOne

color(255)olabilir color(-1)bir bayt kaydetmek için
Kritixi Lithos
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.