Fai un po 'di neve!


18

Il tuo compito: generare un fiocco di neve Koch all'ennesima profondità. Non è necessario creare un fiocco di neve Koch completo, solo un lato del triangolo iniziale. Wikipedia sui fiocchi di Koch: https://en.wikipedia.org/wiki/Koch_snowflake .

Regole:

  • Il programma deve generare un lato del fiocco di neve di Koch all'ennesima profondità.
  • L'output deve essere ASCII.
  • È possibile generare l'intero fiocco di neve; questo non è richiesto.
  • Si applicano le regole standard per input / output e scappatoie e cose.
  • Gli spazi bianchi non contano, purché tutti i personaggi siano nel posto giusto l'uno rispetto all'altro.
  • Vince il codice più corto!

Casi test:

n = 0:

__

n = 1:

__/\__

n = 2:

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

n = 3:

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

Spero che abbia senso. Si noti che in ciascun caso di test, il frattale può essere diviso in tre parti uguali in lunghezza. Si noti inoltre che la larghezza di ciascun fiocco di neve è tre volte la larghezza della generazione precedente del fiocco di neve.


Cordiali saluti, si è convenuto che questa non è una vittima di questo .
Compagno SparklePony

Non credo che tu abbia definito in modo appropriato quale sia la rappresentazione ASCII corretta dell'ennesima curva di Koch.
orlp

Non sono sicuro che le proporzioni abbiano un senso. Il non duplicato utilizzato __/\__con due sottolineature, che ha reso ogni iterazione costantemente 3 volte più grande della precedente. L'uso di una sola sottolineatura sembra dare delle contraddizioni che iniziano a diventare davvero imbarazzanti in n = 3. Ad esempio, le parti esterne hanno larghezza 12 mentre la parte centrale ha solo larghezza 10, in conseguenza di /_e _\ che sono troppo strette. E anche prima si sta _espandendo al doppio della larghezza di /e \ .
Ørjan Johansen

Penso che /_e _\ siano l'unica parte davvero fatale: i caratteri di sottolineatura devono andare, perché devono essere nella stessa posizione di /e \ . Una volta fatto, le cose possono espandersi di 3 volte da n = 1 in poi (ma n = 0 non si adatta.)
Ørjan Johansen

Purtroppo, no, la parte centrale ha ancora larghezza che non corrisponde alle parti esterne, come evidenziato da n = 3 con larghezza 52 anziché 54 = 2 * 3 ^ 3. Prova uno di questi . Ho incluso le versioni capovolte con le parti mostrate solo da n = 4 o n = 5 - differiscono da quelle verso l'alto in cui vengono rilasciati i trattini bassi.
Ørjan Johansen,

Risposte:


10

Haskell , 308 300 299 byte

modifiche:

  • -4 byte: Cambiare zipWith(+)per zipWith(-)e regolazione codifiche e offset sono liberato di ogni segno di negazione.
  • -1 byte: l'ulteriore modifica della codifica ha permesso di eliminare diversi nomi di variabili #utilizzando r=reverseinvece la corrispondenza diretta del modello.
  • -2 byte: utilizzo di un operatore invece di alfanum per zipWith(-).
  • -1 byte: definizione o=[0,0]per abbreviare le costanti dell'elenco.
  • -1 byte: unione di due rami di ?.
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]

Provalo online! (Purtroppo, qualsiasi cosa più grande di n = 3 diventa orribilmente incartata e illeggibile, ma puoi copiarla su un altro programma per vederlo.)

variazioni

  • Se cambi [6]in [6,4,4], otterrai un intero fiocco di neve. Provalo online!
  • Se rimuovi ,3..gcd 3x, ottieni una curva nello stile con cui questa domanda è stata originariamente data. Provalo online!
  • O entrambi contemporaneamente: provalo online!

Come funziona

  • k è la funzione principale, ci vuole un Int n e restituisce un String.
  • iterate(>>=(:[1,4,1]))[6]genera un elenco infinito contenente, per ogni n, i giri tra le righe consecutive in quella iterazione di curva, lo stile grafico della tartaruga, come numeri nominalmente tra 0e 5. Ogni iterazione è solo la precedente con i turni 1,4,1intercalati. L'unico motivo per cui le liste secondarie iniziano con 6invece di 0fare il gcdtrucco nel flavoro evitando f 0.
  • scanl1(+)converte le svolte in direzioni "assolute", fino al modulo 6. A 0significa verso destra, quindi ogni numero più alto è di 60 gradi in senso antiorario dal precedente. (Beh, sarebbe 60 gradi se questo fosse un disegno corretto piuttosto che ASCII.)
  • f converte una direzione assoluta in un elenco di coppie (caratteri, codifica offset) che codifica i caratteri da aggiungere alla curva (per le direzioni orizzontali genera due coppie, altrimenti una) e come cambia la posizione relativa.
  • L' #operatore scorre l'elenco precedente di coppie (caratteri, codifica offset), generando coppie effettive (coordinate, caratteri).
  • Principi di codifica:
    • Un personaggio di _/\nominalmente rappresenta una linea tracciata da un angolo iniziale attraverso una cella rettangolare a un angolo finale diverso.
    • Le coordinate delle celle sono nella forma [y,x], dall'alto verso il basso, da sinistra a destra, in modo che ordinino nell'ordine in cui vogliamo stamparle. Le colonne sono basate su 1. Gli elenchi vengono utilizzati al posto delle tuple per l'aritmetica vettoriale più breve con (&)=zipWith(-).
    • Un angolo è indicato con le stesse coordinate [y,x]della cella nella sua parte superiore sinistra. Ciò garantisce che tutti gli offset da un angolo alle celle vicine siano non negativi, evitando costanti negative.
    • Tuttavia, le coordinate degli angoli vengono passate negate per consentire a tutte le operazioni vettoriali di essere sottrazioni anziché aggiunte, il che evita tutti gli altri segni espliciti.
    • Un elenco di codifica offset è [y1,x1,x2,y2]dove si [y1,x1]trova l'offset delle coordinate dall'angolo iniziale alla cella del carattere ed [y2,x2]è l'offset dall'angolo finale alla cella del carattere. Questo significa:
      • Gli elenchi di codifica per le direzioni 3.. 5sono solo il contrario degli elenchi per 0... 2, consentendo loro di essere generati con [id,r]<*>.
      • Tutta l'aritmetica vettoriale necessaria può essere eseguita utilizzando (&)=zipWith(-)un elenco di codifica o il suo contrario.
  • Dopo aver ordinato l'elenco delle coppie (coordinate, caratteri), vengono passate a ?, che genera il finale Stringda esse.
    • In x?l@(([_,w],c):r) xè la coordinata x del carattere precedente mostrato su questa linea, o 0se all'inizio di una linea; lè l'intero elenco corrente, wè la coordinata x del carattere successivo da aggiungere, cè il carattere ed rè l'elenco rimanente.
    • In questa fase le coordinate y non sono più necessarie. Poiché ogni riga contiene caratteri e il primo carattere di ogni riga si trova alla sinistra della fine della precedente, l'inizio di nuove righe viene rilevato controllando se la coordinata x è diminuita.
    • Underscore ha un valore ASCII maggiore di \e /, quindi viene ordinato per ultimo se si sovrappone a un altro carattere nella stessa posizione. Pertanto viene rilevato un carattere di sottolineatura ridondante verificando che una coordinata x sia stata ripetuta.

Bello! Accetterò questo se non ci sono più attività su questa domanda oggi.
Compagno SparklePony
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.