L'ouragan Matthew et les éclairs

27

Défi

Inspirés par ce défi et le méchant ouragan Matthew , nous allons générer dynamiquement des éclairs.

n = 15:

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

Contribution

Entier positif ndétermine la profondeur de la foudre.

Règles et contraintes

  • /et \doit être utilisé
  • La probabilité guidant la direction de la foudre est la suivante:
    • 25% se divise en 2 chemins
    • 25% Le chemin atteint l'impasse
    • 25% va à gauche
    • 25% va bien
    • Il y a quelques exceptions concernant le chevauchement et l'impasse ci-dessous:
  • Le code ne doit pas être déterministe, un nouvel éclair doit être généré aléatoirement à chaque fois
  • Les boulons ne doivent pas se chevaucher: par exemple, s'il y a déjà un boulon à gauche du boulon actuel, le boulon actuel doit soit se terminer, soit aller à droite, mais pas aller à gauche ou se scinder (la probabilité s'applique toujours, dans ce cas, il devient 50% fin / 50% à droite)
  • S'il n'existe pas un autre chemin de partage disponible, le chemin ne doit pas se terminer: par exemple au début quand il n'y a qu'un seul chemin, le chemin ne doit pas se terminer jusqu'à ce qu'il se divise, s'applique également lorsqu'il y a plusieurs chemins mais tous sauf un chemin sont morts , (la probabilité devient 33% divisée / 33% gauche / 33% droite) votre objectif est d'atteindre le bas
  • Des espaces peuvent être ajoutés sur la gauche (tout ce dont vous avez besoin ne devrait être que de la hauteur-1)
  • Cependant, vous voulez générer le boulon qui vous appartient, vous pouvez aller de bas en haut, de gauche à droite, etc. Tant que toutes les règles ci-dessus sont satisfaites

Un autre exemple

n = 10

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

L'ouragan Matthew tire apparemment des boulons rouges dans le ciel, appelés sprites

Restez en sécurité et amusez-vous au golf! Veuillez jouer au golf de manière responsable uniquement lorsque vous êtes dans une zone sûre !!

Zukaberg
la source
7
Stay safe and have fun golfing!Peut-être aussi précisez que si EAS frappe, abandonnez tout et suivez les ordres! Le code de golf n'est pas votre priorité dans une telle situation.
Erik the Outgolfer
17
@EriktheGolfer vous n'êtes donc pas un vrai golfeur.
Blue
4
Je ne crois pas que "le chemin le plus au centre devrait être celui qui atteint le sol" est cohérent avec le reste de la description de génération aléatoire. Par exemple, il est possible au hasard que le boulon d'origine se divise deux fois, puis que les deux boulons du milieu se terminent; comment contourner cette possibilité tout en préservant les probabilités indiquées?
Greg Martin
De plus, que se passe-t-il si (par exemple) les deux premières étapes sont toutes deux des scissions? Ensuite, les deux boulons du milieu se touchent, ce qui semble problématique mais n'est pas non plus exclu par les cas spéciaux.
Greg Martin
@GregMartin Bon point sur la partie la plus centrale, à l'origine, j'espérais qu'il génère un boulon équilibré, mais maintenant que j'y pense même sans cette contrainte environ 50% du temps, il devrait se retrouver quelque part au milieu, une profondeur sur 15 n'aurait que 1 à 2% de chances d'atterrir à droite ou à gauche. Je vais supprimer cette règle. Et pour la partie de fractionnement en 2 étapes, la seule chose à éviter est qu'aucun 2 chemins ne doit joindre 2 chemins: \/à tout moment.
Zukaberg

Réponses:

6

Perl, 92 90 89 84 octets

Comprend +1 pour -n

Donnez de la hauteur sur 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$_

Explication

Si vous appelez le décalage du point de départ 0 (un point est au coin d'une case de caractère), alors sur la ligne suivante, vous pouvez être allé à gauche ou à droite (ou non) et vous pouvez vous retrouver avec des points sur les décalages -1,1. La ligne suivante donne -2,0,2les décalages possibles, etc. Ils diffèrent tous par 2. Si vous appelez ensuite le caractère en bas à gauche d'un point pair et le caractère en bas à droite impair, vous pouvez étendre cela à l'attribution de pair ou impair à chaque position de caractère sur une rangée telle que l'alternance paire et impaire (en fait, tout l'avion est carrelé en damier). Une position paire peut avoir un /ou , une position impaire peut avoir un \ou .

Le caractère juste avant a /est dans une position étrange, il pourrait donc être soit \ou , mais \/est interdit, donc seul est possible. De même, le caractère après a \ doit être un (en supposant que la ligne est remplie avec suffisamment d'espaces à gauche et à droite pour que les limites de ligne ne soient pas un problème). Ainsi, un éclair continue sur la ligne suivante toujours directement en dessous de a \ou en dessous de a /. Dans les deux cas , le point le plus bas se trouve au milieu et la rangée suivante peut avoir l' une , /, \ou /\directement en dessous du sommet 2 caractères. Donc, pour générer la ligne suivante, je peux simplement remplacer tout \ou/par l'une de ces 4 extensions avec une probabilité égale (vous pouvez également remplacer indépendamment le premier caractère par ou /et le deuxième caractère par ou \). En perl, vous pouvez le faire avec quelque chose comme:

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

Si la ligne résultante contient cependant \/(interdit rejoindre) ou non /ou \à tous (dies de boulons et ne parvient pas à fond) , le résultat est invalide. Dans ce cas, je jette toute la rangée et j'essaye simplement à nouveau. Une continuation valide existe toujours et si vous essayez assez souvent, une sera trouvée (par exemple, tout meurt à l'exception d'un flux). Il s'agit d'une distribution de probabilité légèrement différente de l'algorithme anti-chevauchement suggéré, mais je pense que c'est en fait mieux car il n'a pas de biais directionnel. La validité peut être testée de manière golfique en utilisant

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

Le problème ici est que la substitution aléatoire est tellement looooong et que toutes ces \échappées mangent aussi des octets. J'ai donc décidé de créer mes lignes à l'aide de chaînes de chiffres et de remplacer les chiffres appropriés par , /et \juste avant l'impression. Le remplacement aléatoire de base est

53|16*rand

ce qui donne un de 53, 55, 61ou 63avec une probabilité égale. J'interprète ensuite 5et 1comme , 3comme \et 6comme /. Cela explique l'impression de la ligne:

say y|3615|\\/ |r

Dans une compétition de golf sérieuse, je commencerais maintenant à explorer systématiquement des formules magiques alternatives, mais cela devrait être assez bon (dans les 3 octets optimaux)

Le reste des composantes du programme:

1x$_.6

Cela initialise $_(voir la carte suivante) les espaces de hauteur suivis de a /. Il s'agit d'une ligne invisible au-dessus de la première en cours d'impression et garantit que le champ est suffisamment large pour que le boulon ne puisse jamais manquer d'espace à gauche

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

Je vais traiter cette même hauteur initiale de chaîne en imprimant une nouvelle ligne à chaque fois

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

Enregistrez la ligne actuelle dans $;. Si le remplacement s'avère invalide, restaurez $_depuis$;

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

Faites la substitution réelle. Je n'ai pas à vérifier ce qui est avant /ou après \car ce doit être un espace. Ceci est pratique car l'espace peut être représenté par 1ou 5. Étant donné que j'ai seulement rempli la chaîne à gauche, l'espace après le \peut encore être absent, alors rendez ce caractère facultatif

/3|6/>/36/

Vérifiez si la nouvelle ligne est valide

Ton Hospel
la source
+1 Neat! vous devriez inclure ce testeur en ligne perl -M5.010 main.pl <<< 25 , j'ai obtenu de belles sorties!
Zukaberg
Voulez-vous expliquer un peu comment cela fonctionne? Je m'amuse trop à les générer haha, honnêtement je ne m'attendais pas à de si bons résultats.
Zukaberg
Malheureusement, vous devez ajouter 3 octets-n , car l'espace et le tiret comptent également. La même règle s'applique aux arguments de ligne de commande. Voir "Invocations spéciales", deuxième puce: je les compte comme une différence de nombre de caractères jusqu'à l'invocation équivalente la plus courte sans eux.
Erik the Outgolfer
1
@EriktheGolfer Non, +1 est OK car ce programme fonctionne très bien à partir de la ligne de commande en utilisant -nEseulement 1 caractère de plus que -E. (Voir l'article que vous avez référencé. Cela supprime également la nécessité de -M5.010) Je présente toujours mon code sous forme de fichiers car il est plus pratique, mais je compte toujours les options comme celle-ci: si elle peut être exécutée à partir de la ligne de commande, je ne compte pas l'espace et le tiret. Si elle doit être dans un fichier (par exemple parce qu'il utilise do$0) Je ne compte l'espace et le tableau de bord
Ton Hospel
@TonHospel Oh, je ne savais pas que tu avais l'habitude -E. Si oui, vous êtes bon.
Erik the Outgolfer
0

JavaScript (ES6), 154 octets

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>

J'ai eu du mal avec l'implémentation jusqu'à ce que je voie la réponse de @ TonHospel, à quel point elle a simplement dégénéré en port. Exemple de sortie:

         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \
Neil
la source