Perl, 92 90 89 84 байта
Включает +1 для -n
Дайте рост на 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$_
объяснение
Если вы называете смещение начальной точки 0 (точка находится в углу поля символа), то в следующей строке вы можете перейти влево или вправо (или нет) и в конечном итоге получить точки со смещением -1,1. В следующей строке -2,0,2указываются возможные смещения и т. Д. Все они отличаются на 2. Если затем вы называете символ слева внизу от точки четным, а символ справа внизу нечетным, вы можете расширить его, назначив четное или нечетное каждой позиции символа. в ряду, который чередует четное и нечетное (фактически вся плоскость выложена плиткой в шахматном порядке). Четная позиция может иметь /или , нечетная позиция может иметь \или .
Символ непосредственно перед a /находится в нечетной позиции, так что это может быть либо, \либо , но \/запрещено, поэтому возможно только . Точно так же символ после a \ должен быть a (при условии, что строка дополняется достаточным количеством пробелов слева и справа, поэтому границы строк не имеют значения). Таким образом, молния продолжается в следующем ряду всегда непосредственно ниже \или ниже a /. В любом случае нижняя точка находится в середине , и следующая строка может иметь один из , /, \или /\непосредственно под верхние 2 символов. Таким образом, чтобы создать следующую строку, я могу просто заменить любой \или/любым из этих 4 расширений с равной вероятностью (вы также можете независимо заменить первый символ на или, /а второй символ на или \). В Perl вы можете сделать это с чем-то вроде:
s#\\ | /#(" "," \\","/ ","/\\")[rand 4]#eg
Если результирующая строка, однако, содержит \/(запрещенное соединение) или отсутствует /или \вовсе (болт умирает и не достигает дна), результат недействителен. В этом случае я выбрасываю весь ряд и просто пытаюсь снова. Действительное продолжение всегда существует, и если вы попытаетесь достаточно часто, оно будет найдено (например, все умирает, кроме 1 потока). Это распределение немного отличается от предложенного алгоритма предотвращения перекрытия, но я думаю, что это на самом деле лучше, так как он не имеет направленного смещения. Валидность можно проверить по-гольфистски, используя
m#\\|/#>m#\\/#
Проблема здесь в том, что случайная замена слишком длинная, и все эти \побеги также съедают байты. Так что я решил построить мои строки с помощью строки цифр и заменить соответствующие цифры от , /и как \раз перед печатью. Основная случайная замена
53|16*rand
который дает один из 53, 55, 61или 63с равной вероятностью. Я тогда интерпретирую 5и 1как , 3как \и 6как /. Это объясняет строку печати:
say y|3615|\\/ |r
В серьезных соревнованиях по гольфу я бы начал систематически изучать альтернативные формулы магии, но это должно быть довольно хорошо (в пределах 3 байтов от оптимального)
Остальные компоненты программы:
1x$_.6
Это инициализирует $_(см. Следующую карту) пространство высоты, за которым следует символ /. Это невидимая строка над первой печатаемой и гарантирует, что поле достаточно широкое, так что болт никогда не может выйти из пространства слева
map{ ... ; say ...}(1x$_.6)x$_
Я буду обрабатывать те же начальные значения высоты строки, каждый раз печатая новую строку
$_=$;until$;=$_,...
Сохранить текущую строку в $;. Если замена оказывается недействительной, восстановить $_из$;
s/.6|3.?/53|16*rand/eg
Делать фактическую замену. Мне не нужно проверять, что до /или после, \так как это должен быть пробел. Это удобно, поскольку пространство может быть представлено либо либо, 1либо 5. Поскольку я добавляю строку только слева, пробел после \буквы все еще может отсутствовать, так что сделайте этот символ необязательным
/3|6/>/36/
Проверьте правильность новой строки
Stay safe and have fun golfing!Возможно, также укажите, что если EAS ударит, откажитесь от всего и выполняйте приказы! Гольф-код не является вашим приоритетом в такой ситуации.