<#; "#: ={},>
}=}(.);("@
Інший спів з @ MartinBüttner, який на самому ділі зробив більшість майже всі ігри в гольф для цього. Переробивши алгоритм, нам вдалося зовсім небагато зменшити розмір програми!
Спробуйте в Інтернеті!
Пояснення
Швидкий ґрунтовник Labrinth:
Лабіринт - це двоскладова мова на основі стека. Є два стеки, основний і допоміжний стек, і вискакування з порожнього стека дає нуль.
На кожному перехресті, де є кілька шляхів, щоб покажчик інструкцій рухався вниз, верхня частина основного стеку перевіряється, щоб побачити, куди йти далі. Негатив - поворот ліворуч, нуль - прямо вперед, а позитив - поворот праворуч.
Два стеки цілих чисел з довільною точністю - це не велика гнучкість у відношенні параметрів пам'яті. Щоб здійснити підрахунок, ця програма фактично використовує два стеки як стрічку, при цьому зміщення значення з однієї стеки на іншу схоже на переміщення вказівника пам'яті вліво / вправо по комірці. Це не зовсім так, як це, оскільки нам потрібно перетягнути лічильник циклу з нами по дорозі вгору.
По-перше, <
і >
на будь-якому кінці спливають зміщення та обертають рядок коду, який зміщений на один або вліво, або вправо. Цей механізм використовується для того, щоб змусити код працювати в циклі - <
з'являється нуль і обертає поточний рядок ліворуч, ставлячи IP праворуч від коду, а >
з'являється ще один нуль і фіксує рядок назад.
Ось що відбувається з кожною ітерацією стосовно діаграми, наведеної вище:
[Section 1]
,} Read char of input and shift to aux - the char will be used as a counter
to determine how many elements to shift
[Section 2 - shift loop]
{ Shift counter from aux
" No-op at a junction: turn left to [Section 3] if char was EOF (-1), otherwise
turn right
( Decrement counter; go forward to [Section 4] if zero, otherwise turn right
= Swap tops of main and aux - we've pulled a value from aux and moved the
decremented counter to aux, ready for the next loop iteration
[Section 3]
@ Terminate
[Section 4]
; Pop the zeroed counter
) Increment the top of the main stack, updating the count of the number of times
we've seen the read char
: Copy the count, to determine how many chars to output
[Section 5 - output loop]
#. Output (number of elements on stack) as a char
( Decrement the count of how many chars to output; go forward to [Section 6]
if zero, otherwise turn right
" No-op
[Section 6]
} Shift the zeroed counter to aux
[Section 7a]
This section is meant to shift one element at a time from main to aux until the main
stack is empty, but the first iteration actually traverses the loop the wrong way!
Suppose the stack state is [... a b c | 0 d e ...].
= Swap tops of main and aux [... a b 0 | c d e ...]
} Move top of main to aux [... a b | 0 c d e ...]
#; Push stack depth and pop it (no-op)
= Swap tops of main and aux [... a 0 | b c d e ...]
Top is 0 at a junction - can't move
forwards so we bounce back
; Pop the top 0 [... a | b c d e ... ]
The net result is that we've shifted two chars from main to aux and popped the
extraneous zero. From here the loop is traversed anticlockwise as intended.
[Section 7b - unshift loop]
# Push stack depth; if zero, move forward to the <, else turn left
}= Move to aux and swap main and aux, thus moving the char below (stack depth)
to aux
; Pop the stack depth