Третий Зенит!

19

Этот вызов был опубликован как часть конкурс LotM апреле 2018 года.


Brain-Flak - это язык тьюринга и тарпита, который приобрел довольно большую известность здесь, на PPCG. Память о языке состоит из двух стеков, а «скрытый» третий стек был обнаружен на Wh е в мастере , что приводит к некоторым интересным новым способам мышления программы Brain-зенитной.

Итак, как насчет того, чтобы дать этому бедному скрытому третьему стеку больше видимости? Давайте создадим язык, в котором третий стек получит признание, которого он заслуживает! Здесь я представляю вам Третий Flak .

Язык

В Third-Flak есть только один стек, называемый третьим стеком. Операторы работают на третьем стек таким же образом , что они делают в Брейн-Flak, но здесь нет [], {}, <>nilads и не {...}монады (так только допустимые символы в программе третьего Flak являются ()[]<>). Вот что делает каждый оператор (будут приведены примеры, представляющие третий стек со списком, где последний элемент является вершиной стека):

  • ()является единственным двухсимвольным оператором в Third-Flak. Увеличивает вершину третьего стека на 1. Пример: [1,2,3][1,2,4]

  • (, [, <: Все открытия скобки, которые не охвачены в предыдущем случае нажать 0на третий стек. Пример: [1,2,3][1,2,3,0]

  • )выталкивает два элемента из третьего стека и возвращает их сумму. Пример: [1,2,3][1,5]

  • ]извлекает два элемента из третьего стека и возвращает результат вычитания первого из второго. Пример: [1,2,3][1,-1]

  • >выталкивает элемент из третьего стека. Пример [1,2,3][1,2]

А вот и другие правила языка:

  • В начале выполнения третий стек содержит только один 0.

  • Запрещено иметь пустой []или<> внутреннюю программу (в любом случае они будут noops, если следовать семантике Third-Flak, но на самом деле они имеют другое значение в Brain-Flak, которое здесь невозможно воссоздать).

  • Круглые скобки всегда должны быть сбалансированы, за исключением того факта, что завершающие закрывающие скобки в конце программы могут отсутствовать. Например, [()<(()допустимая программа третьего флага (и третий стек в конце программы будет[1,0,1] ).

  • Программа может содержать только шесть разрешенных символов ()[]<> . Программы гарантированно не являются пустыми.

Примечание: предыдущие правила подразумевают, что вам не придется сталкиваться с ситуациями, когда вам нужно выскочить из пустого стека.

Соревнование

Проще, напиши интерпретатор для Third-Flak. Ваша программа должна принимать в качестве входных данных программу третьего флага и возвращать в качестве выходных данных состояние третьего стека в конце программы.

Ваш выходной формат является гибким до тех пор, пока можно однозначно прочитать из него состояние третьего стека и одно и то же число всегда кодируется одинаково (это просто способ сказать, что любой выходной формат не является явным способом пытаться обмануть нормально).

Ваш выходной выбор может ограничить диапазон номеров, которыми вы можете управлять, если это не упрощает задачу (поскольку это будет лазейка по умолчанию ).

Контрольные примеры

Для каждого тестового случая первая строка является входной, а вторая строка выходным стеком, представленным как разделенный пробелами список чисел, где вершина стека является последним элементом.

[()<(()
0 1 0 1

[((((()()()()()))
0 0 0 5

((([()][()][()])))
-3

[<<(((()()()())(((((
0 0 0 0 0 4 0 0 0 0 0

[()]<(([()])><[()]
-1 0 -1

(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(()()()()())(())(())(())(())(())(())(()())(())(())(())(()())(()()()())(())(()()()()())(()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(())(())(()())(())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()())(()())(())(()()()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(())(())(())(()()())(())(())(()()())(())(())(()()())(())(()()()()())(()())(()()()()())(()()())(())(()()())(())(())(())(()())(()()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(())(())(())(()()())(())(())(())(()())(())(()())(()()()())(())(())(()()()()())(()())(()())(())(()()())(())(())(())(())(()()())(()())(())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(()()()()())(()()()()())(())(()()())(())(())(()())(())(()()()()())(())(()()()()())(())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(()()()()())(())(()()()()())(())(())(())(()())(())(()()()()())(())(())(()())(())(()())(())(()())(()())(()())(()())(())(()()()()())(()())(())(()()()()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(())(()()())(())(())(())(()())(()()()())(())(())(()())(())(()()()()())(())(())(()()()()())(())(())(()()()()())(())(())(()())(())(()())(())(()())(())(()())(())(()())(()())(()())(()())(()())(()())(())(()()())(())(())(()())(())(()()()()())(()())(()()()()())(()()())(())(())(()())(())(())(()()()()())(()()()())(()())(()())(()()())(())(()())(())(()()()()())(()())(()()()()())(())(())(())(()()()())(()()()())(()()
718 2
Лео
источник
Стек инициализируется с 0? В противном случае [()]нарушается правило, согласно которому нам не нужно беспокоиться о выталкивании из пустого стека
Джо Кинг,
1
@JoKing Yep: «В начале выполнения третий стек содержит только один 0». Может быть, мне стоит немного выделить эту часть, я боялся, что ее было бы слишком легко пропустить.
Лев
Ой, я не знаю, как я это пропустил
Джо Кинг,
7
Вычеркнуто е все еще е.
Волшебник Пшеницы
2
Если кто -то не могут видеть , что перечеркнутые eнаходится здесь .
user202729

Ответы:

21

Brain-Flak , 276 байт

{({}<>)<>}<>{(((()()()()()){})((({}){})())(({})({}{}([{}])(<>))))((()()(){[()]<{}>}{}){()<{{}}>}{}<<>({}({})())>{()(<{}>)}{}<>)<>}<>{(([{}]()<>)){{}({}())((){[()](<({}())((){[()](<({}())((){[()](<{}([{}]{})>)}{}){(<{}{}>)}{}>)}{}){(<{}({}{})>)}{}>)}{}){(<{}{}({}())>)}}{}<>}<>

Попробуйте онлайн!

Вы должны были знать, что это идет.

Nitrodon
источник
4

Retina 0.8.2 , 64 48 46 байт

\(\)
_
[([<]
¶
+1`¶(.*)\)|(.*)¶\2]|¶.*>
$1
%`_

Попробуйте онлайн! Выводит стек снизу вверх. Работает только с неотрицательными целыми числами, а последний контрольный пример слишком медленный, поэтому ссылка содержит только три контрольных примера. Объяснение: Стек неявно предшествует программе, поэтому он начинается с пустой строки, которая представляет один ноль. ()Nilad превращаются в _который используется для подсчета в Унарном, в то время как другие открытых скобках превратились в символы новой строки , которые толкают ноль в стек , поскольку они встречаются. Закрывающие скобки затем обрабатываются по одному, так что стек будет правильным; )удаляет предыдущую строку, добавив сверху два элемента вместе, ]удаляет верхний элемент и соответствует его от предыдущего элемента в стеке , таким образом , вычитая его, и>просто удаляет верхний элемент. Наконец стек преобразуется в десятичную. Изменить: Сохранено 2 байта благодаря @Leo.

Нил
источник
Для чего $3? (отличный ответ, так или иначе!)
Лев
@Leo Это остатки предыдущего гольфа. Спасибо, что заметили это!
Нил
4

Python 3 , 145 144 132 122 116 109 104 байта

-7 байт благодаря Лео!

И - 5 благодаря Линн!

s=[0]
for i in input().replace('()',' '):s+=i in']>) 'and(i<'!'or(2-ord(i)%5)*s.pop())+s.pop(),
print(s)

Попробуйте онлайн!

Довольно стандартная реализация.Теперь не так читабельно. Я разочарован тем, что не смог найти более короткий способ проверки между начальными и конечными скобками.

Некоторые попытки однострочников:

  • 124 байта (анонимная функция):

    lambda c:[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())or s for s in[[0]]for i in c.replace('()',' ')][0]
  • 115 байт (полная программа):

    s=[0];[s.append(i in']>) 'and(i<'!'or~-']>)'.index(i)*s.pop())+s.pop())for i in input().replace('()',' ')];print(s)

Добавить досадно дольше, чем простое назначение

Джо Кинг
источник
~-']>)'.index(i)можно (2-ord(i)%5)сохранить 4 байта.
Линн
2

Рубин , 98 91 байт

->s{a=[i=0];s.chars{|c|a<<("([<"[c]?s[i,2]["()"]?1:0:a.pop*~-"]>)".index(c)+a.pop);i+=1};a}

Попробуйте онлайн!

Мой исходный код работал по духу аналогично ответу Джона Кинга на Python, так что перед циклом просмотра исходных символов мы заменили все () подстроки другим символом в качестве отдельного оператора.

Однако, по крайней мере в Ruby, оказалось, что гольфист не делает этого, а предпочитает немного более громоздкий подход. Здесь мы поддерживаем дополнительный индексатор, iотслеживающий нашу позицию в исходной строке, и всякий раз, когда встречается открывающая скобка, мы выполняем предварительную проверку, если наши текущие + следующие символы s[i,2]образуют ()оператор. В этом случае мы нажимаем 1 вместо 0 на вершине стека и позволяем закрытию )делать свою работу на следующем шаге.

Кирилл Л.
источник
1

05AB1E , 25 байтов

΄()1:v"0+0\0->"žuykè.V})

Попробуйте онлайн!

объяснение

Î                           # initialize the stack with 0 and the input
 „()1:                      # replace any occurrence of "()" in the input with 1
      v                }    # for each char y in this string
                žuyk        # get its index in the string "()[]<>{}"
       "0+0\0->"    è       # use this to index into the string "0+0\0->"
                     .V     # eval
                        )   # wrap the stack in a list
Emigna
источник
1

R , 182 177 байт

function(P){for(k in utf8ToInt(gsub("\\(\\)",7,P))%%8){if(k%in%0:4)F=c(0,F)
if(k==7)F[1]=F[1]+1
if(k==1)F=c(F[2]+F[3],F[-3:0])
if(k==5)F=c(F[2]-F[1],F[-2:0])
if(k==6)F=F[-1]}
F}

Попробуйте онлайн!

Возвращает стек, где верхняя часть стека является первой, а нижняя часть стека является последней.

Свопы ()с , 7а затем вычисляет кодовые точки по модулю 8 , чтобы получить различные числовые значения, которые легче и golfier для работы с чем строки.

Работать с началом вектора в R лучше, поэтому мы строим стек таким образом.

Затем он видит ), или когда k==1он добавляет дополнительный ноль к вершине стека, так как его можно добавить и удалить.

Giuseppe
источник
1

Цейлон, 285 266 байт

function f(variable String c){variable Integer[]s=[0];value o=>[s[0]else nothing,s=s.rest][0];void u(Integer i)=>s=[i,*s];while(c!=""){if(c[0:2]=="()"){u(1);c=c.rest;}switch(c[0])case(')'){u(o+o);}case(']'){u(-o+o);}case('>'){noop(o);}else{u(0);}c=c.rest;}return s;}

Попробуйте онлайн!

(Сохранено 19 байт благодаря предложению Льва.)

Отформатировано и прокомментировано:

// Interpreter for ThirdFlak
// Question:    /codegolf//q/163242/2338
// This answer: /codegolf//a/163403/2338
//
// This function takes the code as a string, and returns the value
// of the stack as a sequence of Integers.
function f(variable String c) {
    // stack, in the beginning just a single 0.
    // Top element of the stack is the first, because push + pop is easier this way.
    variable Integer[] s = [0];
    // pop – used like an Integer variable (not a function – this saves the `()`), but has side effects.
    value o =>
        // `s[0]` is the first element of the stack. We tell the compiler
        // that it is non-null (otherwise we'll get an error at run time)
        // using the `else nothing`. `s.rest` is `s` without its first element.
        // Both together are wrapped into a 2-tuple, of which we then take just
        // the first element, to have both together in an expression instead
        // the longer way using an accessor block with a temporary variable and a return.
        // value o {
        //   value r = s[0] else nothing;
        //   s = s.rest;
        //   return r;
        // }
        [s[0] else nothing, s = s.rest][0];
    // push
    void u(Integer i) =>
        // a tuple enumeration, using the spread argument.
        s = [i, *s];
    // the main loop
    while (c != "") {
        if (c[0:2] == "()") {
            // »`()` is the only two-characters operator in Third-Flak. It increases the top of the third stack by 1.«
            // As `)` alone adds the two top elements together, we can just push a one here, and let the handling for `)` do the rest.
            u(1);
            c = c.rest;
        }
        switch (c[0])
        case (')') {
            // »`)` pops two elements from the third stack and pushes back their sum.«
            u(o + o);
        }
        case (']') {
            // »`]` pops two elements from the third stack and pushes back the result of subtracting the first from the second.«
            // As the o written first is the first one, we can't write this as a subtraction.
            u(-o + o);
        }
        case ('>') {
            // »`>` pops an element from the third stack.«
            // `o;` alone is not a valid statement, so we pass it to the `noop` function.
            noop(o);
        }
        else {
            // all other valid code characters are `(`, `[`, `<`, which all just push a 0.
            u(0);
        }
        c = c.rest;
    }
    return s;
}

Попробуйте онлайн!

Пауло Эберманн
источник
Я действительно не знаю Цейлона, но, возможно, вы могли бы снять первый корпус коммутатора и использовать остальную часть, чтобы управлять всеми открывающими скобками :)
Лев
Хм, я думаю, это могло бы сработать ... это изменило бы поведение при неправильном вводе, но это не проблема.
Паŭло Эберманн