Trzeci Flak!

19

To wyzwanie zostało opublikowane w ramach wyzwania LotM z kwietnia 2018 r


Brain-Flak to język Turinga-Tarpona, który zyskał całkiem sporo sławy tutaj na PPCG. Pamięć języka składa się z dwóch stosów, ale „ukryty” trzeci stos został odkryty przez Wh e at Wizard , co prowadzi do kilku nowych interesujących sposobów myślenia o programach Brain-Flak.

A co powiesz na zwiększenie widoczności tego słabego ukrytego trzeciego stosu? Stwórzmy język, w którym trzeci stos ma takie uznanie, na jakie zasługuje! Tutaj przedstawiam wam Trzeci Flak .

Język

W Third-Flak jest tylko jeden stos, zwany trzecim stosem. Operatorzy pracują na trzecim stosu w ten sam sposób, co robią w Brain-Flak, ale tutaj nie ma [], {}, <>nilads i nie {...}monada (więc tylko dopuszczalne znaki w programie innej Flak są ()[]<>). Oto, co robi każdy operator (podane zostaną przykłady reprezentujące trzeci stos z listą, w której ostatni element jest na górze stosu):

  • ()jest jedynym dwuznakowym operatorem w Third-Flak. Zwiększa górę trzeciego stosu o 1. Przykład: [1,2,3][1,2,4]

  • (, [, <: Wszystkie nawiasy otwierające, które nie zostały objęte poprzednim przypadku naciskasz 0do trzeciego stosie. Przykład: [1,2,3][1,2,3,0]

  • )wyskakuje dwa elementy z trzeciego stosu i odsuwa ich sumę. Przykład: [1,2,3][1,5]

  • ]wyskakuje dwa elementy z trzeciego stosu i odsuwa wynik odejmowania pierwszego od drugiego. Przykład: [1,2,3][1,-1]

  • >wyskakuje element z trzeciego stosu. Przykład [1,2,3][1,2]

A oto inne zasady języka:

  • Na początku wykonywania trzeci stos zawiera tylko jedno 0.

  • Zabronione jest posiadanie pustego []lub <>wewnątrz programu (i tak byłyby noops, jeśli podążałyby za semantyką Third-Flak, ale w rzeczywistości mają inne znaczenie w Brain-Flak, którego nie można tutaj odtworzyć).

  • Nawiasy zawsze muszą być zrównoważone, z wyjątkiem faktu, że na końcu programu mogą brakować końcowych nawiasów zamykających. Na przykład [()<(()jest to poprawny program Third-Flak (a trzeci stos na końcu programu byłby [1,0,1]).

  • Program może zawierać tylko sześć dozwolonych znaków ()[]<>. Programy z pewnością nie będą puste.

Uwaga: poprzednie zasady sugerują, że nie będziesz musiał radzić sobie z sytuacjami, w których musisz wyskoczyć z pustego stosu.

Wyzwanie

Proste, napisz interpretera dla Third-Flak. Twój program musi przyjąć jako dane wejściowe program Third-Flak i zwrócić jako wynik stan trzeciego stosu na końcu programu.

Twój format wyjściowy jest elastyczny, o ile możliwe jest jednoznaczne odczytanie z niego stanu trzeciego stosu, a ten sam numer jest zawsze kodowany w ten sam sposób (Jest to tylko sposób na stwierdzenie, że każdy format wyjściowy, który nie jest rażący próbować oszukiwać jest w porządku).

Twój wybór danych wyjściowych może ograniczyć zakres liczb, którymi możesz zarządzać, pod warunkiem, że nie będzie to trywialne wyzwanie (ponieważ byłaby to domyślna luka ).

Przypadki testowe

Dla każdego przypadku testowego pierwszym wierszem jest wejście, a drugim wierszem stos wyjściowy reprezentowany jako lista liczb oddzielona spacjami, gdzie góra stosu jest ostatnim elementem.

[()<(()
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
Lew
źródło
Czy stos inicjowany jest wartością 0? W przeciwnym razie [()]łamie zasadę, że nie musimy się martwić wyskakiwaniem z pustego stosu
Jo King
1
@JoKing Yep: „Na początku wykonywania trzeci stos zawiera tylko jedno 0”. Może powinienem nieco podkreślić tę część, bałem się, że zbyt łatwo byłoby przegapić.
Leo
Ups, nie wiem, jak mi tego brakowało
Jo King
7
Przekreślone e jest nadal e.
Wheat Wizard
2
Jeśli ktoś tego nie widzi, przekreślony ejest tutaj .
user202729,

Odpowiedzi:

21

Brain-Flak , 276 bajtów

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

Wypróbuj online!

Musiałeś wiedzieć, że to nadchodzi.

Nitrodon
źródło
4

Retina 0.8.2 , 64 48 46 bajtów

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

Wypróbuj online! Wysyła stos od dołu do góry. Działa tylko z nieujemnymi liczbami całkowitymi, a ostatni przypadek testowy jest zbyt wolny, więc link zawiera tylko trzy przypadki testowe. Objaśnienie: Stos domyślnie poprzedza program, więc zaczyna się jako pusty ciąg znaków, który reprezentuje pojedyncze zero. ()Nilad zostaje przekształcony w _których stosuje się liczyć w jednoskładnikowa, natomiast pozostałe wsporniki otwarte są włączone do nowej linii, które popychają zero na stosie, ponieważ są one spotkaliśmy. Nawiasy zamykające są następnie przetwarzane pojedynczo, aby stos był poprawny; )usuwa poprzedniego przełamane, dodając dwie górne elementy łącznie, ]usuwa element górny i dopasowuje się od poprzedniego elementu w stosie tak odejmując i>po prostu usuwa górny element. Na koniec stos jest konwertowany na dziesiętny. Edycja: Zapisano 2 bajty dzięki @Leo.

Neil
źródło
Co to jest $3za? (w każdym razie świetna odpowiedź!)
Leo
@Leo To pozostałość po poprzednim golfie. Dzięki za wykrycie tego!
Neil
4

Python 3 , 145 144 132 122 116 109 104 bajtów

-7 bajtów dzięki Leo!

I - 5 dzięki Lynn!

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

Wypróbuj online!

Całkiem standardowe wdrożenie. Teraz jednak nie tak czytelny. Jestem rozczarowany, że nie mogłem znaleźć krótszego sposobu na sprawdzenie między nawiasami początkowymi i końcowymi.

Niektóre próby wprowadzenia jednej linii:

  • 124 bajty (funkcja anonimowa):

    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 bajtów (pełny program):

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

Append jest irytująco dłuższy niż zwykłe przypisanie

Jo King
źródło
~-']>)'.index(i)można (2-ord(i)%5)zapisać 4 bajty.
Lynn
2

Ruby , 98 91 bajtów

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

Wypróbuj online!

Mój początkowy kod działał podobnie w duchu do odpowiedzi Pytona Jo Kinga, więc przed zapętleniem znaków źródłowych zastąpiliśmy wszystkie ()podciągi innym znakiem, jako odrębnym operatorem.

Jednak przynajmniej w Ruby okazało się, że golfista tego nie robi, ale raczej wybrał nieco bardziej kłopotliwe podejście. W tym przypadku utrzymujemy dodatkowy indeksator, który iśledzi naszą pozycję w łańcuchu źródłowym, i za każdym razem, gdy napotkamy nawias otwierający, sprawdzamy, czy nasze bieżące + następne znaki s[i,2]tworzą ()operator. W takim przypadku wciskamy 1 zamiast 0 na stosie i pozwalamy zamknięciu )wykonać swoją pracę w następnym kroku.

Kirill L.
źródło
1

05AB1E , 25 bajtów

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

Wypróbuj online!

Wyjaśnienie

Î                           # 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
źródło
1

R , 182 177 bajtów

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}

Wypróbuj online!

Zwraca stos, w którym górna część stosu jest pierwsza, a spód stosu ostatnia.

Zamienia ()z, 7a następnie oblicza punkty kodowe mod 8, aby uzyskać wyraźne wartości liczbowe, które są łatwiejsze i bardziej golfowe w obsłudze niż łańcuchy.

Golfier pracuje z początkiem wektora w R, więc konstruujemy stos w ten sposób.

Następnie widzi znak „ )lub” k==1i dodaje dodatkowe zero na górze stosu, ponieważ golfista może go dodać i usunąć.

Giuseppe
źródło
1

CJam , 29 bajtów

0q")]>([<""+-;U"er"U+"/')*~]p

Wypróbuj online!

0q                              Push 0, input
  ")]>([<""+-;U"er              Translate )]>([< to +-;UUU
                  "U+"/')*      Replace U+ by )
                          ~     Eval as CJam code
                           ]p   Wrap and pretty-print stack
Lynn
źródło
1

Cejlon, 285 266 bajtów

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;}

Wypróbuj online!

(Zapisano 19 bajtów dzięki sugestii Leo.)

Sformatowane i skomentowane:

// 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;
}

Wypróbuj online!

Paŭlo Ebermann
źródło
Naprawdę nie znam Ceylonu, ale może mógłbyś usunąć pierwszą obudowę przełącznika i użyć drugiej części do zarządzania wszystkimi nawiasami otwierającymi :)
Leo
Hmm, myślę, że to może zadziałać ... zmieniłoby zachowanie nieprawidłowych danych wejściowych, ale to nie jest problem.
Paŭlo Ebermann