Ураган Метью та блискавки


27

Виклик

Натхнені цим викликом і неприємним ураганом Метью , ми будемо динамічно створювати кілька блискавок.

n = 15:

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

Вхідні дані

Позитивний цілий номер nвизначає глибину блискавки.

Правила та обмеження

  • /і \слід використовувати
  • Ймовірність направлення блискавки така:
    • 25% Розбивається на 2 доріжки
    • 25% Шлях доходить у глухий кут
    • 25% йде ліворуч
    • 25% йде правильно
    • Нижче наведено кілька винятків щодо перекриття та глухого кута:
  • Код не повинен бути детермінованим, кожен раз, коли кожен блискавка повинен генеруватися випадковим чином
  • Болти не повинні перекриватися: наприклад, якщо вже є болт ліворуч від поточного болта, то струм болта повинен або закінчуватися, або йти праворуч, але не йти ліворуч або розщеплюватися (ймовірність все-таки діє, в цьому випадку він стає на 50% кінцем / 50% право)
  • Якщо не існує іншого доступного розділеного шляху, шлях не повинен закінчуватися: наприклад, на початку, коли існує лише 1 шлях, шлях не повинен закінчуватися, поки він не розщепить, також застосовується, коли існує кілька шляхів, але всі, крім одного шляху, мертві , (ймовірність стає 33% роздвоєною / 33% зліва / 33% правою), ваша мета - досягти нижньої частини
  • Білі простори можна додати зліва (все, що вам знадобиться, має бути лише висотою-1)
  • Однак ви хочете генерувати болт саме вам, ви можете переходити знизу вгору, зліва направо і т.д.

Ще один приклад

n = 10

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

Ураган Метью, мабуть, стріляє червоними болтами в небо, звані спрайтами

Будьте в безпеці та отримуйте задоволення від гольфу! Будьте відповідальні за гольф лише тоді, коли ви знаходитесь у безпечній зоні !!


7
Stay safe and have fun golfing!Можливо, також уточнюйте, що якщо EAS завдає удару, відмовтесь від усього і виконайте замовлення! Гольф-код не є вашим пріоритетом у такій ситуації.
Ерік Аутгольфер

17
@EriktheGolfer Ви тоді не справжній гольфіст.
Блакитний

4
Я не вірю, що "Найбільш центральний шлях повинен бути той, хто доходить до землі" відповідає решті опису випадкових поколінь. Наприклад, випадково можливо, щоб оригінальний болт роздвоєний двічі, а потім, щоб середні два болта закінчилися; як можна скасувати таку можливість, зберігаючи вказані ймовірності?
Грег Мартін

Крім того, що станеться, якщо (наприклад, перші два кроки обидва розбиваються? Потім середні два болта торкаються один одного, що здається проблематичним, але також не виключається особливими випадками.
Грег Мартін

@GregMartin Добре в центрі більшої частини, спочатку я сподівався, що він створить врівноважений болт, але тепер, коли я думаю про це навіть без цього обмеження, приблизно 50% часу він повинен закінчитися десь посередині, глибина з 15 мав би шанс на 1-2% лише там, де розташована права або ліва частина більшої стежки. Я вилучу це правило. А для розділення частини, що розділяється на 2 етапи, єдине, що слід запобігти, - це те, що жодна 2 контура не повинна з'єднувати 2 контури: \/у будь-якій точці.
Зукаберг

Відповіді:


6

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/

Перевірте, чи дійсний новий рядок


+1 Охайно! Ви повинні включити цей інтернет-тестер perl -M5.010 main.pl <<< 25 , я отримав кілька приємних результатів!
Зукаберг

Розумієте трохи пояснити, як це працює? Мені дуже весело генерувати їх ха-ха, я, чесно кажучи, не очікував таких хороших результатів.
Зукаберг

На жаль, вам потрібно додати 3 байти-n , тому що простір та тире також враховуються. Це ж правило стосується аргументів командного рядка. Див. "Спеціальні виклики", друга точка: Я вважаю їх різницею підрахунку символів до найкоротшого еквівалентного виклику без них.
Ерік Аутгольфер

1
@EriktheGolfer Ні, +1 - це нормально, оскільки ця програма прекрасно працює з командного рядка, за допомогою -nEякого лише на 1 символ більше -E(див. Статтю, на яку ви посилаєтесь. Це також позбавляється від потреби -M5.010) Я завжди представляю свій код як файли, оскільки це Це зручніше, але я завжди вважаю такі параметри: Якщо це можна запустити з командного рядка, я не рахую пробіл та тире. Якщо він повинен бути в файлі (наприклад , тому що він використовує do$0) я зробити порахувати простір і тире
Ton Hospel

@TonHospel О, я не знав, що ти використовуєш -E. Якщо так, то ви добрі.
Ерік Аутгольфер

0

JavaScript (ES6), 154 байти

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>

Я боровся з реалізацією, поки не побачив відповідь @ TonHospel, і в цей момент він просто переродився в порт. Вибірка зразка:

         /\
        / /\
       /\   \
        /\   \
         /\  /
          / /\
         / / /\
            / /\
            \   \
             \
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.