Uragano Matthew e i fulmini


27

Sfida

Ispirati da questa sfida e dal cattivo uragano Matthew , genereremo dinamicamente alcuni fulmini.

n = 15:

   \
   /\
  /  \
 /   /
/\  /\
 /  \ \
/   / /\
   /\ \
  / /  \
 /\ \  /\
  /  \ \
 /\  /  
   \
    \
    /\

Ingresso

L'intero positivo ndetermina la profondità del fulmine.

Regole e vincoli

  • /e \dovrebbe essere usato
  • La probabilità che guida la direzione del fulmine è la seguente:
    • 25% si divide in 2 percorsi
    • 25% Path raggiunge il vicolo cieco
    • Il 25% va a sinistra
    • Il 25% va bene
    • Di seguito sono riportate alcune eccezioni relative alla sovrapposizione e al vicolo cieco:
  • Il codice non dovrebbe essere deterministico, un nuovo fulmine dovrebbe essere generato casualmente ogni volta
  • I bulloni non devono sovrapporsi: ad es. Se esiste già un bullone a sinistra del bullone corrente, il bullone corrente deve terminare o andare a destra, ma non andare a sinistra o dividere (la probabilità si applica comunque, in questo caso diventa fine del 50% / 50% a destra)
  • Se non esiste un altro percorso diviso disponibile, il percorso non deve terminare: ad esempio all'inizio quando esiste solo 1 percorso, il percorso non deve terminare fino a quando non si divide, vale anche quando ci sono più percorsi ma tutti tranne un percorso sono morti , (la probabilità diventa suddivisione del 33% / 33% a sinistra / 33% a destra) il tuo obiettivo è raggiungere il fondo
  • Gli spazi bianchi possono essere aggiunti a sinistra (tutto ciò di cui hai bisogno dovrebbe essere solo altezza-1)
  • Comunque tu voglia generare il bullone dipende da te, puoi andare dal basso verso l'alto, da sinistra a destra, ecc. Fintanto che tutte le regole sopra sono soddisfatte

Un altro esempio

n = 10

 \
 /
 \
 /\
  /\
 / /
/\ \
 / /\
 \   \
 /

L'uragano Matthew sta apparentemente lanciando fulmini rossi nel cielo, chiamati sprite

Stai al sicuro e divertiti giocando a golf! Si prega di giocare a golf responsabilmente solo quando ci si trova in un'area sicura !!


7
Stay safe and have fun golfing!Forse anche specificare che se l'EAS colpisce, abbandonare tutto e seguire gli ordini! Il codice del golf non è la tua priorità in una situazione del genere.
Erik the Outgolfer,

17
@EriktheGolfer non sei un vero golfista allora.
Blu,

4
Non credo che "il percorso più centrale dovrebbe essere quello che raggiunge il suolo" è coerente con il resto della descrizione di generazione casuale. Ad esempio, è possibile casualmente che il bullone originale si divida due volte e poi che i due bulloni centrali finiscano; come può essere ignorata questa possibilità pur mantenendo le probabilità indicate?
Greg Martin,

Inoltre, cosa succede se (ad esempio) i primi due passaggi sono entrambi suddivisi? Quindi i due bulloni centrali si toccano, il che sembra problematico ma non è escluso dai casi speciali.
Greg Martin,

@GregMartin Un buon punto nella parte centrale, in origine speravo che generasse un bullone bilanciato, ma ora che ci penso anche senza quel vincolo circa il 50% delle volte dovrebbe finire da qualche parte nel mezzo, una profondità di 15 avrebbe solo l'1-2% di probabilità dove la destra o la sinistra della maggior parte del percorso atterra. Rimuoverò quella regola. E per i 2 passaggi che dividono la parte, l'unica cosa da evitare è che nessun 2 percorsi dovrebbe unire 2 percorsi: \/in qualsiasi momento.
Zukaberg,

Risposte:


6

Perl, 92 90 89 84 byte

Include +1 per -n

Dare altezza su STDIN:

perl -M5.010 bolt.pl <<< 15

bolt.pl:

#!/usr/bin/perl -n
map{$_=$;until$;=$_,s/.6|3.?/53|16*rand/eg,/3|6/>/36/;say y|3615|\\/ |r}(1x$_.6)x$_

Spiegazione

Se chiami l'offset del punto iniziale 0 (un punto si trova nell'angolo di una casella di carattere), nella riga successiva puoi essere andato a sinistra o a destra (o no) e puoi finire con punti sugli offset -1,1. La riga successiva indica -2,0,2come possibili offset ecc. Differiscono tutti per 2. Se poi chiami il personaggio in basso a sinistra di un punto pari e il carattere in basso a destra dispari puoi estenderlo all'assegnazione di pari o dispari a ogni posizione del personaggio su una fila tale che si alternino pari e dispari (in effetti l'intero piano è piastrellato a scacchiera). Una posizione pari può avere /o , una posizione dispari può avere \o .

Il personaggio appena prima di a /è in una posizione strana, quindi potrebbe essere uno \o , ma \/è proibito, quindi è possibile solo . Allo stesso modo, il carattere dopo a \ deve essere a (supponendo che la riga sia riempita con spazi sufficienti a sinistra e a destra, quindi i confini della riga non sono un problema). Quindi un fulmine continua nella riga successiva sempre direttamente sotto a \o sotto a /. In entrambi i casi il punto più basso è nel mezzo e la riga successiva può avere uno dei , /, \o /\direttamente sotto i primi 2 caratteri. Quindi per generare la riga successiva posso semplicemente sostituire qualsiasi \o/con una di queste 4 espansioni con uguale probabilità (puoi anche sostituire in modo indipendente il primo carattere con oe /il secondo carattere con o \). In perl potresti farlo con qualcosa del tipo:

s#\\ | /#("  "," \\","/ ","/\\")[rand 4]#eg

Se la riga risultante contiene comunque \/(unione proibita) o no /o \affatto (il bullone muore e non raggiunge il fondo) il risultato non è valido. In tal caso, butto via l'intera riga e semplicemente riprovo. Esiste sempre una continuazione valida e se ci provi abbastanza spesso ne verrà trovata una (ad es. Tutto muore tranne 1 flusso). Questa è una distribuzione di probabilità leggermente diversa dall'algoritmo suggerito anti-sovrapposizione, ma penso che sia effettivamente migliore poiché non ha distorsioni direzionali. La validità può essere testata in modo golfistico utilizzando

m#\\|/#>m#\\/#

Il problema qui è che la sostituzione casuale è così lunga e tutte queste \fughe mangiano anche byte. Così ho deciso di costruire le mie righe usando stringhe di cifre e sostituire le cifre appropriate con , /e \appena prima di stampare. La sostituzione casuale di base è

53|16*rand

che dà una delle 53, 55, 61o 63con la stessa probabilità. Poi interpreto 5e 1come , 3come \e 6come /. Questo spiega la stampa di righe:

say y|3615|\\/ |r

In una seria competizione di golf ora inizierei a esplorare sistematicamente formule magiche alternative, ma questo dovrebbe essere abbastanza buono (entro 3 byte dall'ottimale)

Il resto dei componenti del programma:

1x$_.6

Questo inizializza $_(vedi la mappa successiva) agli spazi di altezza seguiti da a /. Questa è una riga invisibile sopra la prima che viene stampata e si assicura che il campo sia abbastanza largo in modo che il bullone non possa mai esaurire lo spazio a sinistra

map{ ... ; say ...}(1x$_.6)x$_

Elaborerò la stessa altezza iniziale della stringa volte a stampare una nuova riga ogni volta

$_=$;until$;=$_,...

Salva la riga corrente in $;. Se la sostituzione risulta non valida ripristinare $_da$;

s/.6|3.?/53|16*rand/eg

Effettua la sostituzione effettiva. Non devo controllare ciò che è prima /o dopo \poiché deve essere uno spazio. Questo è conveniente poiché lo spazio può essere rappresentato da uno 1o 5. Dal momento che ho solo riempito la stringa a sinistra dello spazio dopo che \può ancora essere assente, quindi rendere quel carattere opzionale

/3|6/>/36/

Controlla se la nuova riga è valida


+1 pulito! dovresti includere questo tester online perl -M5.010 main.pl <<< 25 , sto ottenendo dei bei risultati!
Zukaberg,

Ti dispiace spiegare un po 'come funziona? Mi sto divertendo troppo a generarli ahah, onestamente non mi aspettavo risultati così buoni.
Zukaberg,

Sfortunatamente, devi aggiungere 3 byte per-n , perché contano anche lo spazio e il trattino. La stessa regola è per gli argomenti della riga di comando. Vedi "Invocazioni speciali", secondo punto elenco: le conto come differenza nel conteggio dei caratteri nell'invocazione equivalente più breve senza di loro.
Erik the Outgolfer,

1
@EriktheGolfer No, +1 va bene perché questo programma funziona bene dalla riga di comando usando -nEquale è solo 1 carattere in più di -E. (Vedi l'articolo a cui hai fatto riferimento. Questo elimina anche la necessità di -M5.010) Presento sempre il mio codice come file perché è più conveniente, ma conto sempre opzioni come questa: se può essere eseguito dalla riga di comando, non conto lo spazio e il trattino. Se si deve essere in un file (ad esempio, perché usa do$0) Io faccio contare lo spazio e il cruscotto
Ton Hospel

@TonHospel Oh, non sapevo che tu l'abbia usato -E. Se è così, sei bravo.
Erik the Outgolfer,

0

JavaScript (ES6), 154 byte

f=(n,r=[],s=" ".repeat(n)+"/",t=s.replace(/ \/|\\ |\\$/g,_=>"  /  \\/\\".substr(Math.random()*8&6,2)))=>n?/^ +$|\\\//.test(t)?f(n,r,s):f(n-1,[...r,t],t):r
<input type="number" min=1 oninput=o.textContent=f(this.value).join`\n`><pre id=o>

Ho lottato con l'implementazione fino a quando non ho visto la risposta di @ TonHospel, a quel punto è appena degenerata in un porto. Uscita campione:

         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \
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.