Hurrikan Matthew und die Blitzschläge

27

Herausforderung

Inspiriert von dieser Herausforderung und dem fiesen Hurrikan Matthew werden wir dynamisch einige Blitze erzeugen.

n = 15:

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

Eingang

Positive Ganzzahl nbestimmt die Tiefe der Blitzrunde.

Regeln und Einschränkungen

  • /und \sollte verwendet werden
  • Die Wahrscheinlichkeit, die die Richtung des Blitzes bestimmt, ist wie folgt:
    • 25% Teilt sich in 2 Pfade auf
    • 25% Pfad erreicht Sackgasse
    • 25% gehen nach links
    • 25% gehen nach rechts
    • Es gibt einige Ausnahmen bezüglich Überlappung und Sackgasse:
  • Der Code sollte nicht deterministisch sein, ein neuer Blitz sollte jedes Mal zufällig generiert werden
  • Die Schrauben sollten sich nicht überlappen: Wenn sich z. B. links von der aktuellen Schraube bereits eine Schraube befindet, sollte die aktuelle Schraube entweder enden oder nach rechts gehen, aber nicht nach links gehen oder sich teilen (die Wahrscheinlichkeit gilt weiterhin, in diesem Fall wird sie zu 50% enden) / 50% richtig)
  • Wenn es keinen anderen verfügbaren aufgeteilten Pfad gibt, sollte der Pfad nicht enden: ZB sollte der Pfad am Anfang, wenn es nur einen Pfad gibt, nicht enden, bis er sich aufteilt. Dies gilt auch, wenn es mehrere Pfade gibt, aber alle außer einem Pfad tot sind (Wahrscheinlichkeit wird 33% geteilt / 33% links / 33% rechts) Ihr Ziel ist es, den Boden zu erreichen
  • Auf der linken Seite können Leerzeichen hinzugefügt werden (alles, was Sie brauchen, sollte nur die Höhe 1 sein)
  • Wie auch immer Sie den Bolzen generieren möchten, Sie können von unten nach oben, von links nach rechts usw. gehen, solange alle obigen Regeln erfüllt sind

Ein anderes Beispiel

n = 10

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

Der Hurrikan Matthew schießt anscheinend rote Sprites in den Himmel

Bleib sicher und hab Spaß beim Golfen! Bitte golfen Sie verantwortungsbewusst nur, wenn Sie sich in einer sicheren Gegend befinden !!

Zukaberg
quelle
7
Stay safe and have fun golfing!Möglicherweise geben Sie auch an, dass Sie bei einem Streik von EAS alles aufgeben und die Anweisungen befolgen müssen! Golf Code ist nicht Ihre Priorität in einer solchen Situation.
Erik the Outgolfer
17
@EriktheGolfer du bist dann kein echter Golfer.
Blue
4
Ich glaube nicht, dass "der zentralste Pfad derjenige sein sollte, der den Boden erreicht", im Einklang mit dem Rest der Beschreibung der Zufallsgenerationen steht. Beispielsweise ist es zufällig möglich, dass die ursprüngliche Schraube zweimal geteilt wird und dann die beiden mittleren Schrauben enden. Wie kann diese Möglichkeit unter Beibehaltung der angegebenen Wahrscheinlichkeiten außer Kraft gesetzt werden?
Greg Martin
Was passiert auch, wenn (zum Beispiel) die ersten beiden Schritte beide Teilungen sind? Dann berühren sich die beiden mittleren Bolzen, was problematisch erscheint, aber auch von den Sonderfällen nicht ausgeschlossen wird.
Greg Martin
@GregMartin Guter Punkt in der Mitte, ursprünglich hatte ich gehofft, damit einen ausgeglichenen Bolzen zu erzeugen, aber jetzt, wo ich darüber nachdenke, sollte er auch ohne diese Einschränkung etwa 50% der Zeit irgendwo in der Mitte enden, in einer Tiefe von 15 hätten nur eine Chance von 1-2%, wenn der am weitesten rechts oder links liegende Pfad landet. Ich werde diese Regel entfernen. Und für den 2-Stufen-Teil ist das einzige, was zu verhindern ist, dass keine 2 Pfade 2 Pfade verbinden sollten: \/an irgendeinem Punkt.
Zukaberg

Antworten:

6

Perl, 92 90 89 84 Bytes

Beinhaltet +1 für -n

Gib die Höhe auf STDIN an:

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$_

Erläuterung

Wenn Sie den Versatz des Startpunkts 0 nennen (ein Punkt befindet sich an der Ecke eines Zeichenfelds), können Sie in der nächsten Zeile nach links oder rechts gegangen sein (oder nicht) und Punkte auf Versätzen erhalten -1,1. Die nächste Zeile gibt -2,0,2mögliche Offsets usw. an. Sie unterscheiden sich alle um 2. Wenn Sie dann das Zeichen links unten von einem geraden Punkt und das Zeichen rechts unten ungerade nennen, können Sie dies so erweitern, dass jeder Zeichenposition gerade oder ungerade zugewiesen werden auf einer Reihe so, dass gerade und ungerade abwechseln (in der Tat ist die ganze Ebene in einem Schachbrettmuster gekachelt). Eine gerade Position kann ein /oder haben , eine ungerade Position kann ein \oder haben .

Das Zeichen kurz vor a /befindet sich an einer ungeraden Position, also könnte es entweder \oder sein , ist aber \/verboten, also nur möglich. Ebenso ist der Charakter nach einem \ muss eine sein (vorausgesetzt , die Reihe mit genug Platz links gepolstert und rechts so die Zeilengrenzen kein Problem sind). Ein Blitz setzt sich also in der nächsten Reihe immer direkt unter einem \oder unter einem fort /. In jedem Fall ist der untere Punkt in der Mitte , und die nächste Zeile kann eine von haben , /, \oder /\direkt unter den oberen 2 Zeichen. Um die nächste Zeile zu generieren, kann ich einfach ein beliebiges \oder ersetzen/durch eine dieser 4 Erweiterungen mit gleicher Wahrscheinlichkeit (Sie können das erste Zeichen auch unabhängig durch oder /und das zweite Zeichen durch oder ersetzen \). In Perl könnte man das mit etwas machen wie:

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

Wenn die resultierende Zeile jedoch enthält \/(verboten beitreten) oder nicht /oder \auf allen (Riegel stirbt und erreicht nicht den Boden) ist das Ergebnis ungültig. In diesem Fall werfe ich die ganze Reihe weg und versuche es einfach noch einmal. Es gibt immer eine gültige Fortsetzung, und wenn Sie oft genug versuchen, wird eine gefunden (z. B. stirbt bis auf einen Durchlauf alles). Dies ist eine etwas andere Wahrscheinlichkeitsverteilung als der vorgeschlagene Anti-Überlappungs-Algorithmus, aber ich denke, dies ist in der Tat besser, da er keine Richtungsverzerrung aufweist. Die Gültigkeit kann auf golferische Weise mit getestet werden

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

Das Problem dabei ist, dass die zufällige Substitution so looooang ist und all diese Escape-Zeichen \auch Bytes essen. Also habe ich beschlossen , meine Zeilen mit Ziffernfolgen zu bauen und ersetzen die entsprechenden Ziffern durch , /und \gerade vor dem Druck. Die grundlegende zufällige Ersetzung ist

53|16*rand

das gibt einer von 53, 55, 61oder 63mit gleicher Wahrscheinlichkeit. Ich interpretiere dann 5und 1als , 3als \und 6als /. Das erklärt den Zeilendruck:

say y|3615|\\/ |r

In einem ernsthaften Golfwettbewerb würde ich jetzt systematisch alternative magische Formeln untersuchen, aber dies sollte ziemlich gut sein (innerhalb von 3 Bytes des Optimums).

Die restlichen Komponenten des Programms:

1x$_.6

Dies initialisiert $_(siehe nächste Karte) Höhenräume, gefolgt von a /. Dies ist eine unsichtbare Zeile über der ersten, die gedruckt wird, und stellt sicher, dass das Feld breit genug ist, damit der Bolzen links nicht leer wird

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

Ich werde dieselbe anfängliche Zeichenkettenhöhe verarbeiten, um jedes Mal eine neue Zeile zu drucken

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

Speichern Sie die aktuelle Zeile in $;. Wenn sich herausstellt, dass die Ersetzung ungültig ist, stellen Sie sie $_von wieder her$;

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

Führen Sie die eigentliche Substitution durch. Ich muss nicht überprüfen , was vor ist /oder nach , \da es muss ein Raum sein. Dies ist praktisch, da der Raum entweder durch 1oder dargestellt werden kann 5. Da ich die Zeichenfolge nur nach links aufgefüllt habe, \darf das Leerzeichen nach dem noch fehlen, machen Sie dieses Zeichen also optional

/3|6/>/36/

Überprüfen Sie, ob die neue Zeile gültig ist

Tonne Hospel
quelle
+1 Ordentlich! Du solltest diesen Online-Tester perl -M5.010 main.pl <<< 25 mit einbeziehen , ich habe ein paar nette Ausgaben bekommen!
Zukaberg
Möchten Sie ein bisschen erklären, wie es funktioniert? Ich habe zu viel Spaß daran, sie zu generieren, haha, ich habe ehrlich gesagt nicht mit so guten Ergebnissen gerechnet.
Zukaberg
Leider müssen Sie 3 Bytes für hinzufügen-n , weil der Raum und der Gedankenstrich auch zählen. Die gleiche Regel gilt für Befehlszeilenargumente. Siehe "Spezielle Aufrufe", zweiter Aufzählungspunkt: Ich zähle diese als Unterschied in der Anzahl der Zeichen bis zum kürzesten entsprechenden Aufruf ohne sie.
Erik der Outgolfer
1
@EriktheGolfer Nein, +1 ist in Ordnung, da dieses Programm von der Befehlszeile aus gut funktioniert und -nEnur 1 Zeichen mehr als -E. (Siehe den Artikel, auf den Sie verwiesen haben. Dadurch wird auch die Notwendigkeit beseitigt. -M5.010) Ich präsentiere meinen Code immer als Dateien, weil es funktioniert ist praktischer, aber ich zähle immer Optionen wie diese: Wenn es von der Kommandozeile ausgeführt werden kann, zähle ich nicht das Leerzeichen und den Bindestrich. Wenn es muss in einer Datei sein (zB weil es verwendet do$0) Ich tun , den Raum verlassen und den Bindestrich
Ton Hospel
@TonHospel Oh, ich wusste nicht, dass du es benutzt hast -E. Wenn ja, bist du gut.
Erik der 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>

Ich kämpfte mit der Implementierung, bis ich die Antwort von @ TonHospel sah, und an diesem Punkt degenerierte es einfach zu einem Hafen. Beispielausgabe:

         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \
Neil
quelle