<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Введення Nсупроводжується рядком, розділеним будь-яким нечисловим символом.
Спробуйте в Інтернеті!
Це було написано у співпраці зі Sp3000 (це означає, що я не міг потрудитися розробити алгоритм, тому він почав працювати над ним, придумав розв’язання 118 байтів, але не міг турбувати його в гольфі, тому я зробив гольф. .. так, для командної роботи).
Пояснення
Звичайний праймер Sp (як звичайно трохи змінений):
- Лабіринт - це двоскладова мова на основі стеків з двома стеками, головною та допоміжною. В основному все відбувається в основному стеку, але ви можете перенести значення на інший, наприклад, щоб повернути їх назад або зберегти на потім.
- Стоси бездонні та заповнені нулями, тому вискакування з порожнього стека не є помилкою.
- Виконання починається з першого дійсного символу (тут угорі зліва). На кожному з’єднанні, де є два або більше можливих шляхів для вказівника інструкції (IP), який слід пройти, верхня частина стека перевіряється, щоб визначити, куди йти далі. Негатив - поворот вліво, нуль - вперед, а позитив - повернути праворуч. Хоча це малося на меті зробити так, щоб код виглядав як звивисті, закручені проходи, ніщо не заважає вам робити "кімнати", де ці умови перевіряються в кожній комірці. Вони можуть спричинити досить непередбачувану поведінку, але чудово підходять для гольфу.
- Вихідний код (і, отже, макет лабіринту) можна змінювати під час виконання, використовуючи
<>^vякий циклічно зміщує рядок або стовпчик або сітку.
" не є.
Ось і ми.
Код починається з <, що є трюком для гольфу, який я кілька разів використовував, починаючи з довгого фрагмента лінійного коду. Він переміщує перший рядок циклічно вліво, з IP-адресою , тому джерело виглядає так:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
Але зараз IP не може рухатися нікуди, тому він виконує <знову. Це триває, поки ми не досягнемо цього стану:
<
,,}:?
.
;(" {(={}{".
,",;=};} }) "{@
У цей момент IP може залишити комірку і почати виконувати другий рядок, починаючи з ?. Отже ось лінійний код розбитий:
? # Read the first integer on STDIN, i.e. N.
:} # Duplicate it and move one copy over to the auxiliary stack.
, # Read the separator character.
,. # Read the first character of the input string and directly print it.
IP тепер входить у цю кімнату 3х2, яка насправді є двома щільно стисненими (перекриваються) 2х2 петлями за годинниковою стрілкою. Перший цикл зчитує та відкидає N-1символи STDIN.
; # Discard the top of the stack. On the first iteration, this is the
# separator we've already read. On subsequent iterations this will be
# one of the N-1 characters from the input string.
( # Decrement N. If this hits zero, we leave the loop, otherwise we continue.
, # Read the next character from STDIN to be discarded.
Тепер ми вводимо другий цикл, який читає залишок вхідного рядка. Ми можемо виявити EOF, тому що ,повернеться -1в цьому випадку, зробивши IP поворот ліворуч.
, # Read a character. Exit the loop if EOF.
( # Decrement it.
Цей декремент насправді не корисний, але ми можемо його скасувати пізніше безкоштовно, і тут він дозволяє нам перекривати дві петлі.
Якщо взяти 5 ABCDEFGHIJKLMNOPвклад як приклад, стек виглядає так:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' 'O' -1 | 5 ... ] Auxiliary
Зауважте, що вони насправді відповідають вхідним символам FGHIJKLMNOP(тому що ми їх зменшили), і що ми насправді не хочемо друкувати перші з них (ми лише відкинули N-1символи, але хочемо пропустити N).
Тепер є короткий лінійний біт, який готує стек до наступного циклу:
; # Discard the -1.
= # Swap the tops of the stacks, i.e. N with the last character.
# By putting the last character on the auxiliary stack, we ensure that
# it doesn't get discarded in the next loop.
} # Move N over to the auxiliary stack as well.
Зараз стеки виглядають так:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' 'N' | 5 'O' ... ] Auxiliary
Вводимо ще 2х2 петлю за годинниковою стрілкою. Це відкидає головні Nсимволи від основного стеку:
; # Discard the top of the main stack.
{ # Pull N over from the auxiliary stack.
( # Decrement it. It it's 0 we leave the loop.
} # Push N back to the auxiliary stack.
Коли ми виходимо з циклу, знову =змінюється той 0і останній символ вхідного рядка. Тепер стеки виглядають так:
Main [ ... 'E' 'F' 'G' 'H' 'I' 'O' | ... ] Auxiliary
Ми хочемо надрукувати вміст основного стеку (за винятком нижнього елемента та всього на 1) зліва . Це означає, що нам потрібно дістати це до допоміжного пакету. Ось що робить наступний цикл 2x2 (за годинниковою стрілкою):
{ # Pull an element over from the auxiliary stack. This is necessary so we
# have a 0 on top of the stack when entering the loop, to prevent the IP
# from turning right immediately.
} # Move the top of the main stack back to the auxiliary stack. If this was the
# bottom of the stack, exit the loop.
) # Increment the current character.
} # Move it over to the auxiliary stack.
Стоси зараз:
Main [ ... | 'F' 'G' 'H' 'I' 'J' 'P] ... ] Auxiliary
Ми переміщуємо першу з них (ту, яку ми не хочемо друкувати) назад до основного стеку {. А тепер вводимо заключний цикл 2x2 ( проти годинникової стрілки ), який друкує решту:
{ # Pull another character over from the auxiliary stack. Exit the loop
# if that's the zero at the bottom of the stack.
. # Print the character.
Нарешті ми припиняємо програму @.
'як лічильний знак? Наприклад:''123321?