:-:_
Попробуйте онлайн! В нижний колонтитул я включил все остальные 4-байтовые решения. (Stack Cats игнорирует все после первого перевода строки.)
Попробуйте наоборот!
объяснение
В -n
флаг очереди на цифровой выход (и вход, но мы не имеем какой - либо), и -m
флаг , как правило , только для удобства игры в гольф , который позволяет избежать избыточной части исходного кода. Это потому, что каждая программа Stack Cats должна иметь зеркальную симметрию. С -m
флагом вы даете ему только первую половину (плюс центральный символ). Таким образом, фактическая программа здесь:
:-:_:-:
Как вы можете видеть из первой ссылки TIO, существует множество 4-байтовых решений, но я выбрал эту для простоты. Stack Cats основан на стеке, и эта программа использует только начальный стек. Поскольку у нас нет входных данных, он содержит один -1
(маркер EOF) поверх бесконечной ямы нулей. Три команды в программе имеют следующее значение:
: Swap the top two stack elements.
- Negate the top stack element (i.e. multiply by -1).
_ Pop a. Peek b. Push b-a.
Итак, вот как программа модифицирует стек (состояния и команды расположены в шахматном порядке, чтобы указать, как каждая команда меняет стек из одного состояния в другое):
: - : _ : - :
-1 0 0 -1 1 0 0 1
0 -1 -1 0 0 1 1 0
0 0 0 0 0 0 0 0
… … … … … … … …
Оказывается, единственная команда, которая действительно что-то здесь делает, - _
это превращает наш маркер EOF в a 1
. Вывод в конце программы неявный, а маркер EOF является необязательным, так что это просто выводит полученное 1
нами.
Теперь, если мы перевернем исходный код из-за неявного зеркалирования, реальная программа станет:
_:-:-:_
Это делает что-то совсем другое:
_ : - : - : _
-1 1 0 0 1 -1 0 -1
0 0 1 1 0 0 -1 -1
0 0 0 0 0 0 0 0
… … … … … … … …
На этот раз в нижней части стека находится еще -1
так оно действует как EOF маркер и только -1
на нем печатается.
...
Теперь, после всего сказанного, поскольку у Stack Cats такие уникальные отношения с обращением кода, я чувствую, что использование -m
- это немного обман. Обычно он предназначен только для сохранения байтов, пропуская избыточную часть исходного кода, но здесь это фактически облегчает задачу и даже сокращает всю программу. Это связано с тем, что изменение полной программы изменит программу только в том случае, если она содержит какой-либо из них <>[]
, что также означает, что программа заканчивает тем, что использует несколько стеков (на самом деле Stack Cats имеет ленту стеков, где все, кроме исходного, заполнены только с нулями для начала). Кроме того, реверсивный его затем просто обменивает <>
и []
пары, которые до сих пор делают выполнение симметричным. Единственный способ нарушить эту симметрию - это использоватьI
, которое делает -]
или-[
или ничего в зависимости от знака вершины стека. Так...
*|]I*:*I[|*
Попробуйте онлайн! Нижний колонтитул снова включает все другие альтернативы с тем же количеством байтов. Некоторые из них выводят 1 / -1, а некоторые выводят 2 / -2, как указано после каждой программы. Я выбрал это, чтобы объяснить случайным образом как один из тех, которые выводят 2.
Попробуйте наоборот!
объяснение
Как я уже сказал, этот немного длиннее. Даже если бы мы использовали-m
для этого обозначение, оно весило бы 6 байтов вместо вышеуказанных 4.
Команды, используемые на этот раз:
* Toggle the least significant bit of the top of the stack.
| Reverse the longest non-zero of prefix on this stack.
[] Move one stack to the left/right and take the top of the current stack with you.
I If the top of the stack is positive, -], if it's negative, -[, otherwise do nothing.
: Swap the top two stack elements.
Первая программа использует только два стека. Это немного грязно в искусстве ASCII, но я буду стараться изо всех сил. Квадратные скобки указывают, в каком стеке находится головка ленты, и я буду помещать команды между каждой парой состояний стека.
[-1]
… 0 0 …
0 0
… …
*
[-2]
… 0 0 …
0 0
… …
| (does nothing)
]
[-2]
… 0 0 …
0 0
… …
I
[2]
… 0 0 …
0 0
… …
*
[3]
… 0 0 …
0 0
… …
:
[0]
… 3 0 …
0 0
… …
*
[1]
… 3 0 …
0 0
… …
I
[-1]
… 3 0 …
0 0
… …
[
[-1]
… 3 0 …
0 0
… …
|
[ 3]
… -1 0 …
0 0
… …
*
[ 2]
… -1 0 …
0 0
… …
Теперь -1
действует как маркер EOF и2
печатается.
Другая программа остается неизменной до [
. До второго практически не меняется I
. Технически мы будем в другом стеке, но без значений на них все они неразличимы. Но тогда разница между I[
и в I]
конечном итоге имеет значение:
*|[I*:*I
[-1]
… 3 0 0 …
0 0 0
… … …
]
[-1]
… 3 0 0 …
0 0 0
… … …
| (does nothing)
*
[-2]
… 3 0 0 …
0 0 0
… … …
И на этот раз у нас нет маркера EOF, но программа все еще выводит -2
.
-
(0x45 = 0b00101101) работает в Jelly --
дает -1, поскольку он определяет литерал -1, тогда какṆ
(0xB4 = 0b10110100) выдает 1, поскольку он выполняет логическое неявного ввода нуля. (Конечно,Ṇ
работает так же хорошо: p)