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 /
знаходиться в непарному положенні, тому він може бути \
або
, але \/
заборонений, тому тільки
можливий. Аналогічно, символ після \
must- 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
Це ініціалізує $_
(див. Наступну карту) на проміжки висот, а потім a /
. Це невидимий рядок над першим надрукованим і гарантує, що поле є достатньо широким, щоб у болта ніколи не було місця зліва
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 завдає удару, відмовтесь від усього і виконайте замовлення! Гольф-код не є вашим пріоритетом у такій ситуації.