Biraz Kar Yap!


18

Göreviniz: n. Derinliğe kadar bir Koch kar tanesi oluşturun. Başlangıç ​​üçgeninin sadece bir tarafı olan tam bir Koch kar tanesi yapmanıza gerek yoktur. Koch pullarında Wikipedia: https://en.wikipedia.org/wiki/Koch_snowflake .

Kurallar:

  • Program Koch kar tanesinin bir tarafını n. Derinliğe kadar üretmelidir.
  • Çıktı ASCII olmalıdır.
  • Sen olabilir bütün kar tanesini üretmek; bu gerekli değildir.
  • Giriş / çıkış ve boşluklar ve diğer şeyler için standart kurallar geçerlidir.
  • Tüm karakterler birbirine göre doğru yerde olduğu sürece boşluk önemli değildir.
  • En kısa kod kazanır!

Test senaryoları:

n = 0:

__

n = 1:

__/\__

n = 2:

      __/\__
      \    /
__/\__/    \__/\__

n = 3:

                        __/\__
                        \    /
                  __/\__/    \__/\__
                  \                /
                  /_              _\
                    \            /
      __/\__      __/            \__      __/\__
      \    /      \                /      \    /
__/\__/    \__/\__/                \__/\__/    \__/\__

Umarım bu mantıklı gelir. Her test durumunda fraktalın eşit uzunlukta üç parçaya ayrılabileceğine dikkat edin. Ayrıca, her bir kar tanesi genişliğinin, önceki kar tanesi neslinin genişliğinin üç katı olduğuna dikkat edin.


Bilginize, bu bir dupe edilemeyeceği kabul edilmiştir bu .
SparklePony Yoldaşı

N. Koch eğrisinin uygun ASCII gösteriminin ne olduğunu uygun bir şekilde tanımladığınızı sanmıyorum.
orlp

Oranların mantıklı olduğundan emin değilim. __/\__İki alt çizgiyle kullanılan dupe olmayan , her yinelemeyi bir öncekinden 3 kat daha büyük hale getirdi. Sadece bir alt çizgi kullanmak, n = 3'te gerçekten garip olmaya başlayan çelişkiler veriyor gibi görünüyor. Orta kısım bir sonucu olarak, sadece genişliği 10 sahipken Örneğin, dış parça 12 genişliği vardır /_ve _\ bu da dar. Ve hatta ondan önce gelmiş _iki kez genişliğine genişleyen /ve \ .
Ørjan Johansen

Bence /_ve _\ sadece gerçekten ölümcül bir parçasıdır - onlar aynı konumda olmamız gerektiğinden alt çizgiler, gitmek gerekir /ve \ . Bu yapıldıktan sonra, işler n = 1'den itibaren 3 kat genişleyebilir (ancak n = 0 uymaz.)
Ørjan Johansen

Ne yazık ki, orta kısım hala 54 = 2 * 3 ^ 3 yerine 52 genişliğine sahip n = 3 ile kanıtlandığı gibi, dış parçalarla eşleşmeyen genişliğe sahiptir. Bunlardan birini deneyin . Sadece n = 4 veya n = 5'ten gösterilen kısımları olan baş aşağı versiyonları ekledim - alt çizgilerin düştüğü yukarıdakilerden farklı.
Ørjan Johansen 30'17

Yanıtlar:


10

Haskell , 308 300 299 bayt

Düzenlemeler:

  • -4 bayt: Değişen zipWith(+)için zipWith(-)ve ayarlama kodlamalar ve uzaklıklar her olumsuzluk işareti kurtulmak lazım.
  • -1 bayt: Kodlamanın daha da ince ayarlanması, doğrudan desen eşleştirme yerine çeşitli değişken adlarının #bırakılmasına izin verdi r=reverse.
  • -2 bayt: için alfanum yerine bir işleç kullanma zipWith(-).
  • -1 byte: o=[0,0]Liste sabitlerini kısaltmayı tanımlar.
  • -1 bayt: iki dalı birleştirme ?.
import Data.List
k n=0?sort(o#(f=<<scanl1(+)(iterate(>>=(:[1,4,1]))[6]!!n)))
x?l@(([_,w],c):r)|x>w='\n':0?l|0<1=([2..w-x]>>" ")++[c|w>x]++w?r
_?_=""
w#((c,l):m)=(l&w,c):r l&(l&w)#m
_#_=[]
f x=zip"_/\\_/\\"([id,r]<*>[0:1:o,[0,1,0,1],o++[1,1]])!!mod x 6<$[1,3..gcd 3x]
(&)=zipWith(-)
r=reverse
o=[0,0]

Çevrimiçi deneyin! (Ne yazık ki, n = 3'ten büyük her şey korkunç bir şekilde sarılır ve okunamaz hale gelir, ancak görmek için başka bir programa kopyalayabilirsiniz.)

Varyasyonlar

Nasıl çalışır

  • kana işlev, bir alır Int nve a döndürür String.
  • iterate(>>=(:[1,4,1]))[6]her bir n için o eğri yinelemesinde ardışık çizgiler arasındaki dönüşleri , kaplumbağa grafik stilini, 0ve arasında nominal olarak sayılar içeren sonsuz bir liste oluşturur 5. Her yineleme, dönüşler 1,4,1aralıklı olarak bir öncekidir. Alt listelerin 6bunun yerine başlamasının tek nedeni, kaçınarak hile 0yapmaktır .gcdff 0
  • scanl1(+)dönüşleri "mutlak" yönlere dönüştürür, modulo 6'ya. A 0sağa doğru demektir, daha sonra her bir yüksek sayı bir öncekinden saat yönünün tersine 60 derecedir. (Peki, bu ASCII yerine düzgün bir çizim olsaydı 60 derece olurdu.)
  • f mutlak bir yönü, eğriye hangi karakterlerin ekleneceğini kodlayan (karakter, ofset kodlama) çiftleri listesine (yatay yönler için iki çift üretir, aksi takdirde bir) ve göreli konumun nasıl değiştiğine dönüştürür.
  • #Gerçek (koordinat karakteri) çiftleri meydana (karakter, ofset kodlama) çifti, önceki liste boyunca operatör dolaşır.
  • Kodlama ilkeleri:
    • _/\Nominal bir karakter, başlangıç ​​köşesinden dikdörtgen bir hücreden farklı bir bitiş köşesine çizilen bir çizgiyi temsil eder.
    • Hücre koordinatları [y,x], yukarıdan aşağıya, soldan sağa formdadır , böylece bunları yazdırmak istediğimiz sıraya göre sıralarlar. Sütunlar 1 tabanlıdır. Listeleri daha kısa vektör aritmetiği için tuples yerine kullanılır (&)=zipWith(-).
    • Bir köşe, [y,x]sol üstteki hücre ile aynı koordinatlarla gösterilir . Bu, bir köşeden komşu hücrelere kadar tüm ofsetlerin negatif olmayan sabit olmasını önleyerek negatif olmamasını sağlar.
    • Bununla birlikte, köşe vektörleri, tüm vektör işlemlerinin toplamalar yerine çıkarmalar olmasına izin vermek için, tüm diğer açık işaretlerden kaçınmak için ihmal edilir.
    • Bir offset kodlayan listesi [y1,x1,x2,y2]burada [y1,x1]karakteri hücreye başlangıç köşesinden ofset koordinat ve [y2,x2]karakter hücreye uç köşesinde kayıktır. Bu şu anlama gelir:
      • Kodlama listeleri tarifini 3.. 5için sadece listelerinin ters olan 0.. 2, bunları oluşturulacak sağlayan [id,r]<*>.
      • Gerekli tüm vektör aritmetiği (&)=zipWith(-)bir kodlama listesi veya bunun tersi kullanılarak yapılabilir.
  • (Koordinat, karakter) çiftlerinin listesini sıraladıktan sonra ?, bunlardan sonuncuyu oluşturan bunlar geçilir String.
    • Olarak x?l@(([_,w],c):r) x, bu satırda gösterilen önceki karakter x koordinatı, ya da 0bir satır başında ise; lgeçerli listenin tamamı, weklenecek bir sonraki karakterin x koordinatı c, karakter ve rkalan listedir.
    • Bu aşamada artık y koordinatlarına gerek yoktur. Her satır karakter içerdiğinden ve her satırın ilk karakteri bir öncekinin sonunun solunda olduğundan, x koordinatının azalıp azalmadığını kontrol ederek yeni satırların başlangıcı algılanır.
    • Alt çizgi ASCII değerinden daha büyüktür \ve /bu nedenle aynı konumda başka bir karakterle çakışırsa en son sıralanır. Böylece, bir x-koordinatının tekrarlandığını kontrol ederek bir gereksiz alt çizgi tespit edilir.

Güzel! Bugün bu soruda daha fazla etkinlik yoksa bunu kabul edeceğim.
SparklePony Yoldaşı
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.