Фуе , 423 байт
Fueue - це езоланг на основі черги, в якому запущена програма є чергою.
)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Спробуйте в Інтернеті!
Як це працює
Це пояснення може або не може вийти з рук. З іншого боку, я не знаю, як це пояснити набагато коротше, сподіваючись, що люди зможуть слідувати.
Фейе-шпаргалка
Докладні відомості див. У статті Вікі esolang , зокрема про деякі функції, які не використовуються в цій програмі.
Початкова програма - це початковий стан черги, який може містити такі елементи:
- Цілі літерали (можна обчислити лише негативні джерела, але негативні), виконуючи їх, друкує символ.
- Вкладені квадратними дужками вкладені вкладені блоки, інертні (зберігаються неушкодженими, якщо на них не діє якась функція).
- Функції, їх аргументи - це елементи, що слідують за ними відразу в черзі:
+*/-%
: ціла арифметика ( -
є одинарною, %
логічне заперечення). Інертне, якщо не вказано число аргументів.
()<
: помістіть елемент у дужки, вийміть дужки з блоку, додайте кінцевий елемент до блоку. Останні два є інертними, якщо не супроводжується блоком.
~:
: поміняти, дублювати.
$
: копія (займає число + елемент). Інерт перед номером.
H
: програма зупинки.
Зауважте, що в той час як []
гніздо, ()
не робіть - останні - це просто окремі функції.
Синтаксис сліду виконання
Білий простір необов’язковий у фуе, за винятком цифр. У наступних слідах виконання він буде використаний для пропонування структури програми, зокрема:
- Коли функція виконується, вона та її аргументи будуть зміщені з навколишніх елементів пробілами. Якщо деякі аргументи є складними, між ними може бути пробіл.
- Багато слідів виконання поділяються на "крапку затримки" зліва, відокремлену від частини праворуч, яка робить суттєві маніпуляції з даними. Дивіться наступний розділ.
Фігурні дужки {}
(не використовуються у фуе) використовуються у слідах для відображення цілого результату математичних виразів. Сюди входять і негативні числа, оскільки Фуе має лише негативні літерали - -
це функція заперечення.
Різні метавимінні назви і ...
використовуються для позначення значень і скорочень.
Затримка тактики
Інтуїтивно, цикли виконання навколо черги, частково змінюючи те, через що вона проходить. Результати функції не можуть бути активовані знову до наступного циклу. Різні частини програми ефективно розвиваються паралельно до тих пір, поки вони не взаємодіють.
В результаті багато коду присвячено синхронізації, зокрема, затримці виконання частин програми до потрібного часу. Варіантів для цього в гольф існує дуже багато, що, як правило, перетворює ці частини на нечитабельні краплі, які можна зрозуміти лише шляхом відстеження циклу їх виконання за циклом.
Ці тактики не завжди будуть окремо згадуватися нижче:
)[A]
затримки A
циклу. (Мабуть, найпростіший і найчитабельніший метод.)
~ef
переставляє елементи e
і f
який також затримує їх виконання. (Мабуть, найменш читабельна, але часто найкоротша для незначних затримок.)
$1e
затримує один елемент e
.
-
і %
корисні для затримки чисел (останні для 0
і 1
.)
- Затримуючи кілька рівних елементів підряд,
:
або $
їх можна використовувати для створення з одного.
(n
загортання n
в дужки, які згодом можна буде зручно зняти. Це особливо важливо для чисельних обчислень, оскільки числа є надто нестабільними, щоб навіть їх можна було скопіювати, не попередньо поставивши їх у блок.
Загальна структура
Решта пояснення розділена на сім частин, кожна для розділу запущеної програми. Більші цикли, після яких більшість із них повторюються, називатимуться "ітераціями", щоб відрізнити їх від "циклів" одиночних проходів по всій черзі.
Ось як поділяється початкова програма між ними:
A: )$$4255%%1(~
B: ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:
D: (H-
E:
F:
G: ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Велика цифра в кінці програми кодує решту в зворотному порядку, дві цифри на символ, з 30 віднімається від кожного значення ASCII (так, наприклад, 10
кодує а (
.)
На більш високому рівні ви можете вважати, що дані цієї програми (починаючи з бінтуму), як течуть справа наліво, але керують потоком зліва направо. Однак на нижчому рівні Fueue весь час заплутує розмежування коду та даних.
- Розділ G декодує бінту на цифри ASCII (наприклад, цифру
0
як ціле число 48
), розділяючи спочатку найменш значущі цифри. Він виробляє одну цифру кожні 15 циклів.
- Розділ F містить отримані цифри значень ASCII (кожне всередині блоку), поки розділ Е не зможе їх споживати.
- Розділ Е обробляє отримані цифри по одній, поєднуючи їх у блоки форми
[x[y]]
, також друкуючи закодований символ кожної пари.
- Розділ D складається з глибоко вкладеного блоку, поступово побудованого з
[x[y]]
блоків таким чином, що після того, як він містить усі цифри, його можна запустити для друку всіх, а потім зупинити всю програму.
- Розділ C займається побудовою секції D, а також відтворює ділянку E.
- Розділ B відтворює розділ C, а також сам кожні 30 циклів.
- Розділ А відраховує цикли до останньої ітерації інших розділів. Потім він перериває секцію B і запускає секцію D.
Розділ А
Розділ A займає планування кінця програми. Для зведення до однієї функції заміни потрібно 4258 циклів ~
, які потім вносять коригування в секцію B, яка зупиняє її основний цикл і замість цього починає виконувати секцію D.
)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
$
Функція створює 4255 копії наступних в %
той час як (
обертає ~
в дужках.
- Кожен останній цикл
%
використовується для перемикання наступного числа між 0
та 1
.
- Коли всі
%
s використовуються, $1
створюється 1 копія [~]
(фактично NOP), а на наступному циклі )
знімає дужки.
Розділ В
Секція B справляється з самою регенерацією, а також новою ітерацією розділу C кожні 30 циклів.
) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] [BkB]
)$ $24% %0 :< [~:)~)] ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1 < < [~:)~)] [BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0 < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
~:) ~)[BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB] ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] (2)
) [BkB] [BkB] $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
:
Дублює великий блок наступний (один екземпляр скорочено [BkB]
), а потім )
видаляє дужку з першої копії.
$$24%%0
налаштовує зворотний відлік, подібний до того, що в розділі А.
- Поки це відлічується,
:<
перетворюється на <<
та ~
замінює два з блоків, оставляючи код нового розділу C останнім.
- Дві
<
функції пакують два кінцевих блоки в перший - це зайве в звичайних ітераціях, але дозволить ~
з розділу А виконати свою роботу в кінці.
- (1) Коли відлік закінчується,
)
знімаються зовнішні дужки. Далі ~:)
перетворюється на ):
та ~)
заміняє a )
на початок розділу C кодом.
- (2) Розділ B тепер повернувся до свого початкового циклу, тоді як a
)
збирається зняти дужки, щоб почати нову ітерацію розділу C.
Під час остаточної ітерації в ~
розділі A з'являється точка (1) вище:
~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] )
У ~
свопи )
через блок і в секції С, запобігаючи розділ В від бути знову запустити.
Розділ С
Розділ C обробляє об'єднання нових знакових пар символів у блок розділу D, а також створює нові ітерації розділу E.
Нижче показано типову ітерацію кодів ASCII цифр x
та їх y
представлення. У першій ітерації вхідні елементи "D" та "E" є початковими [H]
і -
замість цього, як і жоден попередній розділ E, не було виконано для створення жодних пар символів.
C D E
$11~ ) ~<[[+$4--498+*-:~-10)):])<~] [)))~] < [)))~[...]] [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~] < [)))~] [)))~[...][x[y]]]
~~~ ~~~ ) ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~ ~ ) [)))~[....]] [[+$4--498+*-:~-10)):])<~]
~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
[)))~[....]] ~[+$4--498+*-:~-10)):])<~
- Для цього використовується інший метод синхронізації, який я виявив для цієї відповіді. Якщо у вас є кілька функцій підміни
~
підряд, рядок скорочуватиметься приблизно до 2/3 кожного циклу (оскільки один ~
підміняє два наступні), але періодично з залишком ~
s, що спричиняє хаос, ретельно маніпулює подальшим .
$11~
виробляє такий ряд. Наступний ~
поміняє місцями <
на наступний блок. Інший <
в кінці додає новий блок парного числа (цифри x і y як коди ASCII) до блоку розділу D.
- У наступному циклі
~
рядок має ~~
залишок, який заміняє ~
на наступне )
. Інший <
додає розділ D до [)))~]
блоку.
- Далі
~
сам своп замінює наступний блок новим кодом розділу E через блок D розділу. Потім новий залишок ~
міняється )
поперек, і, нарешті, останній ~~
у ~
рядку поміняє одну з них на секцію E так само, як )
вилучив дужки.
Під час остаточної ітерації розділ A ~
поміняв )
поперек розділу B і на розділ C. Однак, розділ C настільки короткочасний, що вже зник, і )
закінчується на початку розділу D.
Розділ D
Розділ D обробляє друк остаточної великої цифри та зупиняє програму. Під час більшості запуску програми це інертний блок, який розділи B – G співпрацюють над побудовою.
(H -
[H]-
⋮
[)))~[H-]] After one iteration of section C
⋮
[)))~[)))~[H-][49[49]]]] Second iteration, after E has also run
⋮
) [)))~[...]] [49[48]] Final printing starts as ) is swapped in
))) ~[...][49[48]]
)) )[49[48]] [...]
)) 49 [48][...] Print first 1
) )[48] [...]
) 48 [...] Print 0
)[...] Recurse to inner block
...
⋮
)[H-] Innermost block reached
H - Program halts
- У першому циклі програми
(
функція зупинки загортається H
в дужки. -
Наступним чином , він буде використовуватися як фіктивний елемент для першої ітерації замість цифр пари.
- Перша об'єднана реальна пара цифр - це
[49[49]]
відповідна фіналу 11
в числівнику.
- Сама остання пара цифр
[49[48]]
(що відповідає 10
початку на числівнику) насправді не включена до блоку, але це не має різниці як )[A[B]]
і )[A][B]
є рівнозначними, як перетворюються на A[B]
.
Після остаточної ітерації, )
поміняється вправо з розділу B, і блок D розділу блокується. На )))~
початку кожного підблоку переконайтеся, що всі частини виконані в правильному порядку. Нарешті, найпотужніший блок містить програму, що H
зупиняє.
Розділ Е
Розділ E обробляє комбіновані пари цифр ASCII, отримані секцією G, і обидві друкує відповідний закодований символ і надсилає блок з комбінованою парою вліво до розділів C і D.
Знову нижче показано типову ітерацію кодів ASCII цифр x
та їх y
представлення.
E F
~ [+$4--498+*-:~-10)):] ) < ~ [y] [x]
) [+$4--498+*-:~-10)):] < [x] [y]
+ $4- - 498 +*- :~ -10 ) ) : [x[y]]
+--- -{-498} +*- ~~{-10} ) ) [x[y]] [x[y]]
+-- - 498 +* -{-10} ~ ) x [y] [x[y]]
+- -{-498} + * 10 x )[y] [x[y]]
+ - 498 + {10*x} y [x[y]]
+ {-498} {10*x+y} [x[y]]
{10*x+y-498} [x[y]]
[x[y]]
- Блоки, що надходять, поміняються місцями, потім блок y додається до блоку x, а весь парний блок копіюється. Один примірник залишиться до кінця для розділів C і D.
- Інша копія знову розблоковується, потім застосовується послідовність арифметичних функцій для обчислення
10*x+y-498
значення ASCII кодованого символу. 498 = 10*48+48-30
, 48
s скасовує кодування ASCII x
і y
при цьому 30
змінює кодування з 00–99
на 30–129
, що включає в себе всі друковані ASCII.
- Потім отримане число залишається для виконання, яке друкує його характер.
Розділ F
Розділ F складається з інертних блоків, що містять коди ASCII цифр. Для більшості запуску програми тут буде не більше двох, оскільки розділ E споживає їх з тією ж швидкістю, з якою виробляє їх G. Однак на завершальній фазі друку 0
тут будуть зібрані кілька зайвих цифр.
[y] [x] ...
Розділ G
Розділ G обробляє розподіл великої кількості наприкінці програми, спочатку найменш значущих цифр, та надсилає блоки з кодами ASCII зліва в інші розділи.
Оскільки у нього немає перевірки зупинки, вона фактично продовжить видавати 0
цифри, коли число знизиться до 0, поки розділ D не зупинить всю програму з H
функцією.
[BkG]
скорочується копія великого блоку стартового коду, який використовується для самовідтворення для запуску нових ітерацій.
Ініціалізація на перших циклах:
) :~ : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
) ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [10...11] [BkG]
Типова ітерація - N
позначає число, яке потрібно розділити:
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [N] [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 ) : [N] : [BkG]
) ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] +5 5 ) [N] [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] ~ 10 N [N] [BkG] [BkG]
) ~:~ ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~] / N 10 [N] [BkG] [BkG]
) ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~] ( {N/10} [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~] : [{N/10}] [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 ) ~ ~ [{N/10}] [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 ) ) [{N/10}] ~ [{N/10}] [N] [BkG] [BkG]
) ~ * [):~[$1(+48]):~+] -10 ~ ) {N/10} [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+] * {-10} {N/10} ) [N] [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~ + {-10*(N/10)} N [{N/10}] [BkG] [BkG]
) ~ ~ [$1(+48] ) ~ ~ {N%10} [{N/10}] [BkG] [BkG]
) [$1(+48] ~ ) {N%10} ~ [{N/10}] [BkG] [BkG]
$1( + 48 {N%10} ) [BkG] [{N/10}] [BkG]
( {48+N%10} BkG [{N/10}] [BkG] New iteration starts
[{48+N%10}] ....
- Затримка краплі тут особливо волохата. Однак єдиним новим трюком затримки є використання
+:5
замість --10
затримки 10
двох циклів. На жаль, 10
у цьому допомогла лише одна з програм.
[N]
І [BkG]
блоки дублюються, то один екземпляр N
ділиться 10
.
[{N/10}]
дублюються, то більше арифметичних функції використовуються для обчислення ASCII коду останньої цифри , N
як 48+((-10)*(N/10)+N)
. Блок з цим кодом ASCII залишається для розділу F.
- Інша копія
[{N/10}]
файлу поміняється між [BkG]
блоками для встановлення початку нової ітерації.
Бонусна квінка (540 байт)
)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63
Спробуйте в Інтернеті!
Оскільки я не знав, який метод буде найкоротшим, спершу спробував кодувати символи у вигляді двоцифрових чисел, розділених (
s. Основний код трохи коротший, але на 50% більше представлення даних компенсує це. Не такий гольф, як інший, як я зупинився, коли зрозумів, що це не переможе. Вона має одну перевагу: вона не потребує реалізації з підтримкою bignum.
Його загальна структура дещо схожа на основну. Розділ G відсутній, оскільки представлення даних безпосередньо заповнює розділ F. Однак у розділі E слід здійснити аналогічний обчислення даних, щоб відновити цифри двоцифрових чисел.