Hurricane Matthew and the Lightning Bolts Challenge

Inspired by this challenge and the nasty Hurricane Matthew, we will be generating some lightning bolts dynamically.

n = 15:

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


Input

Positive Integer n determines the depth of the lightning round.

Rules and Constraints


/ and \ should be used
The probability guiding the lightning's direction is as follow:


  
  25% Splits into 2 paths
  25% Path reaches dead end
  25% Goes Left
  25% Goes Right
  There are a few exceptions regarding overlapping and dead end below:
  

The code should not be deterministic, a new lightning bolt should be generated randomly every time
The bolts should not overlap: e.g. if there is already a bolt to the left of the current bolt, the current bolt should either end or go right, but not go left or split (probability still applies, in this case it become 50%end/50%right)
If there does not exist another available split path, the path should not end: e.g. in the beginning when there is only 1 path, the path should not end until it splits, also applies when there are multiple paths but all except one path are dead, (probability becomes 33%split/33%left/33%right) your goal is to reach the bottom
Whitespaces can be added on the left (all you would need should only be height-1)
However you want to generate the bolt is up to you, you can go from bottom up, left to right, etc. As long as all the rules above are satisfied


Another example

n = 10

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




Stay safe and have fun golfing!
Please golf responsibly only when you are in a safe area!!
Perl, 92 90 89 84 bytes

Includes +1 for -n

Give height on STDIN:

perl -M5.010 bolt.pl &lt;&lt;&lt; 15


bolt.pl:

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


Explanation

If you call the offset of the starting point 0 (a point is at the corner of a character box), then on the next row you can have gone left or right (or not) and can end up with points on offsets -1,1. The next row gives -2,0,2 as possible offsets etc. They all differ by 2. If you then call the character to the lower left of a point even and the character to the lower right odd you can extend that to assigning even or odd to each character position on a row such that even and odd alternate (in fact the whole plane is tiled in a checkerboard pattern). An even position can have a / or , an odd position can have \ or .

The character just before a / is in an odd position so it could be either \ or , but \/ is forbidden so only  is possible. Similarly the character after a \ must be a  (assuming the row is padded with enough spaces to the left and the right so the row boundaries are no issue). So a lightning bolt continues on the next row always directly below a \ or below a /. In either case the lower point is in the middle and the next row can have one of , /, \ or /\ directly below the top 2 characters. So to generate the next row I can simply replace any \ or / by any of these 4 expansions with equal probability (you could also independently replace the first character by  or / and the second character by  or \). In perl you could do this with something like:

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


If the resulting row however contains \/ (forbidden join) or no / or \ at all (bolt dies and does not reach the bottom) the result is invalid. In that case I throw away the whole row and simply try again. A valid continuation always exists and if you try often enough one will be found (e.g everything dies except for 1 flow). This is a slightly different probability distribution from the suggested anti-overlap algorithm, but I think this is in fact better since it has no directional bias. Validity can be testing in a golfish way using

m#\\|/#&gt;m#\\/#


The problem here is that the random substitution is so looooong and all these \ escapes also eat bytes. So I decided to build my rows using strings of digits and replace the appropriate digits by , / and \ just before printing. The basic random replacement is

53|16*rand


which gives one of 53, 55, 61 or 63 with equal probability. I then interpret 5 and 1 as , 3 as \ and 6 as /. That explains the row print:

say y|3615|\\/ |r


In a serious golf competition I would now start to systematically explore alternative magic formulas, but this should be pretty good (within 3 bytes of optimal)

The rest of the components of the program:

1x$_.6


This initializes $_ (see the next map) to height spaces followed by a /. This is an invisible row above the first one being printed and makes sure the field is wide enough so the bolt can never run out of space at the left

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


I will process this same initial string height times printing a new row each time

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


Save the current row in $;. If the replacement turns out to be invalid restore $_ from $;

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


Do the actual substitution. I don't have to check what is before / or after \ since it must be a space. This is convenient since space can be represented by either 1 or 5. Since I only padded the string to the left the space after the \ can still be absent, so make that character optional

/3|6/&gt;/36/


Check if the new row is valid