Відповіді:
*
для виведенняОскільки ви можете виводити, залишаючи рядок у стеці , може бути корисним накопичити рядок, використовуючи, *
а не виводячи за допомогою S
. Скажіть, що ваше завдання було "взяти рядок і додати пробіл", спосіб зробити це з результатом:
S( )S
З *
іншого боку, спосіб зробити це на один байт коротше:
( )*
Проблема полягає в тому, що якщо ваш вихід має багато накопичення, це може коштувати байтів для обробки вихідного елемента на стеку.
Якщо вам потрібно багато використовувати фрагмент коду, є сенс зберігати цей код у стеку та повторювати його та раз у раз. Поки що це просто звичайне програмування Underload. На жаль, тривалий час зберігати значення у стеку є складним і, як правило, призводить до того, що ваш код стане багатослівним, і це справедливо, навіть якщо значення є функцією, а не даними. Це стає набагато гіршим, якщо у вас є кілька функцій, які потрібно повторно використовувати.
У ролі більшої програми, яка може отримати користь від декількох повторно використаних функцій, рішення, яке ви можете використовувати, - це замість того, щоб зробити одну велику функцію, яка може виконувати будь-які їх цілі залежно від способу її виклику (або на основі того, що знаходиться під ним у стеці, або через використання більш довгих послідовностей виклику , ніж просто ^
, ретельно написана функція може відрізнити ^^
від ^:^
від ^*^
від ^~^
, даючи вам чотири різних, досить короткі послідовності). Ви також можете зберігати в цьому "словнику" інші корисні речі, такі як рядки, які ви використовуєте кілька разів. Зауважте, що якщо ви користуєтесь словником сильно, можливо, це має сенс зробити його якоюсь королевою, відсуваючи свою копію назад на стек, так що вам не потрібно копіювати її вручну:
вміти ним користуватися, не втрачаючи можливості використовувати його в майбутньому.
^!!!!^
пошуком стилів (який я також використовував у кількох інших прикладах на сторінці, особливо в розділі мінімізації). Хоча це може не дати найкоротшого пошуку.
Як простий приклад, найбільш часто зустрічається реалізація булевих !()
помилок - це false (тобто ціле число 0), а нульовий рядок - true (тобто ціле число 1), але якщо у вас є проблема, яка сильно базується на логічному XOR, це може зробити більше сенс використовувати нульову рядок як для false, так і ~
для true (цей формат даних може бути перетворений у будь-який інший булівський формат, використовуючи (false)~(true)~^!
, і дозволяє дуже коротко реалізувати *
для XOR.
Можна ще більше продовжити цей загальний принцип і використовувати функції, які пізніше будуть потрібні вашій програмі, як частину ваших значень даних; що дозволяє зберігати функції та дані окремо у стеку. Це може зробити контрольний потік досить заплутаним, але при проведенні гольфу для ремонту часто потрібно зайняти заднє місце, і це не так, як "Underload" все-таки корисний.
(!)
і (~!)
для булів, але ваш шлях здається кращим.
Функціонально-чистий спосіб декрементації церковного числа - це використання функції попередника обчислення лямбда:
\n.n(\p.\z.z($(pT))(pT))(\z.z0[whatever you define the predecessor of 0 to be])
Де 0 = \ x. \ Yy, T = \ x. \ Yx, і $ - наступник.
Перезаписано в Underload, це 28 байт:
(!())~(!())~(!:(:)~*(*)*~)~^!
Це добре, але ми можемо використовувати деякі з корисних властивостей недовантаженням, а саме , що :!
і ()*
не робити не є-OPS. Це означає , що, для ряду n
, :ⁿ!!()()*ⁿ
(де cⁿ
в c
повторному n
раз) дає N-1. Наприклад, якщо це зробити для Церкви цифра 3, це означає:
:::!!()()***
Видаляючи неопарні пари, ми отримуємо:
:*
Що 2.
Отже, це нова і коротша попередня операція:
:(:)~^(!!()())*~(*)~^*
Це на 7 байт коротше.
(()~(:))~:(^!!())*~(*)~^**
все одно на 3 байти коротше.
Навантаженість насправді має два стеки - стек рядків і стек команд, що складають вихідний код. ^
Інструкція Underload дозволяє нам переміщувати рядки з першої стеки до другої. Цим ми можемо заощадити багато непотрібних маніпуляцій стеком.
Наприклад, скажімо, що у нас є (a)(b)(c)
основний стек, і ми хотіли би об'єднати два нижні елементи, ігноруючи (c)
, отримати (ab)(c)
. Наївний спосіб зробити це - повернути стек, щоб отримати, (c)(a)(b)
а потім конкантенувати і поміняти назад:
a~a~*~a*^*~
Це погано. Використовувати a~a~*~a*^
для обертання стека так, як це надзвичайно дорого, і слід уникати, коли це можливо. Замістивши (c)
натомість програмний простір, це можна зробити на чотири байти коротше:
a(*)~*^
Ідея полягає в тому, щоб скористатися інструкціями, які ви хочете виконати, а потім додати інструкцію для відштовхування (c)
в кінці, а потім оцінити результат. Це означає, що нам не потрібно хвилюватися, (c)
поки це не буде відсунуто назад, коли ми закінчимо.
(*)~a*^
, що, на мою думку, є трохи більш складною. По суті ~a*^
це dip
команда від Радості.
eval
команда, я ніколи не бачив такої мови.