Trochę marynaty

19

Moduł piklujący Pythona służy do serializacji, pozwalając zrzucić obiekt w taki sposób, że można go później odtworzyć. W tym celu marynata używa prostego języka opartego na stosie.

Dla uproszczenia będziemy mieli do czynienia z niewielkim podzbiorem tego języka:

(              Push a mark to the stack
S'abc'\n       Push a string to the stack (here with contents 'abc')
l              Pop everything up to the last mark, wrapping all but the mark in a list
t              Pop everything up to the last mark, wrapping all but the mark in a tuple
.              Terminate the virtual machine

Twoim zadaniem jest wdrożenie tego podzbioru języka. Zauważ, że \njest tu dosłownie nowa linia, a nowe linie są w rzeczywistości ważne dla języka.

Dla tych, którzy znają języki GolfScript lub CJam (i l/tdziałają podobnie [i ]odpowiednio.

Wejście

Dla uproszczenia dane wejściowe zawsze będą prawidłowe. W szczególności możesz przyjąć następujące założenia dotyczące danych wejściowych:

  • Ciągi składają się tylko z małych liter i spacji [a-z ]i zawsze będą używać pojedynczych cudzysłowów.
  • Nie będzie żadnych obcych znaków, a wszystkie instrukcje będą takie, jak określono powyżej. Na przykład oznacza to, że znaki nowej linii pojawią się zawsze po łańcuchach.
  • Każdy l/tma pasujące (przed nim i każdy (ma pasujące l/tpo nim. Będzie też co najmniej jeden (.
  • Będzie dokładnie jeden .i zawsze będzie to końcowy charakter.

Możesz pobierać dane z wiersza poleceń, STDIN lub argumentu funkcji. Jeśli chcesz, możesz użyć pojedynczego łańcucha ze znakiem nowej linii zamiast ciągu wielowierszowego, ale proszę podać to w odpowiedzi.

Wynik

Dane wyjściowe powinny być reprezentacją końcowego obiektu, wydrukowane do STDOUT lub zwrócone jako ciąg . Konkretnie:

  • Ciągi są reprezentowane przez otwieranie i zamykanie pojedynczych cytatów z zawartością pomiędzy nimi, np S'abc' -> 'abc'. Nie możesz używać podwójnych cudzysłowów dla tego wyzwania, nawet jeśli są one dozwolone w Pythonie.

  • Listy są reprezentowane przez elementy oddzielone przecinkami otoczone [](np. ['a','b','c']), Podczas gdy krotki są reprezentowane przez elementy oddzielone przecinkami otoczone ()(np ('a','b','c').).

  • Spacje nie mają znaczenia, np. ('a', 'b', 'c' )Jest w porządku.
  • Przed nawiasem zamykającym nie możesz mieć przecinka. Zauważ, że celowo różni się to od reguł składni Pythona, aby ułatwić większość języków, a także utrudnić po prostu zbudowanie listy / krotki w Pythonie, a następnie wygenerowanie jej, ze względu na to, w jaki sposób reprezentowana jest krotka jednoelementowa (w tym wyzwanie, którego potrzebujemy, ('a')a nie ('a',)).

Przykłady

Powyższy tekst może wydawać się zniechęcający, ale poniższe przykłady powinny uczynić sprawę nieco bardziej zrozumiałą.

(l.

Możliwe wyjście: []

(t.

Możliwe wyjście: ()

(S'hello world'
l.

Możliwe wyjście: ['hello world']

(S'string one'
S'string two'
S'string three'
t.

Możliwe wyjście: ('string one', 'string two', 'string three')

(S'a'
(S'b'
S'c'
lt.

Możliwe wyjście: ('a',['b','c'])

((S'a'
S'b'
(lS'c'
t(S'd'
tl.

Możliwe wyjście: [('a', 'b', [], 'c'), ('d')]

((S'a'
((S'b'
t(S'c'
lS'd'
(((ltlS'e'
S'f'
lS'g'
tl.

Możliwe wyjście: [('a',[('b'),['c'],'d',[([])],'e','f'],'g')]

Zasady

  • To jest , więc kod w najmniejszej liczbie bajtów wygrywa.
  • Wszelkie funkcje zaprojektowane do pracy z piklami Pythona są niedozwolone.

Uwaga dotycząca bezpieczeństwa: w prawdziwym kodzie usuwaj tylko źródła, którym ufasz, w przeciwnym razie możesz mieć przykrą cos\nsystem\n(S'rm -rf'\ntR.niespodziankę

Sp3000
źródło
Czy S'abc'\npush abclub 'abc'?
CalculatorFeline

Odpowiedzi:

4

CJam, 63

q{"Slt 1:T;L ]',*'[\+']+ ]',*'(\+')+ [
 0:T; C+"35/T=S/(C#=~}fC

Wypróbuj online

Wyjaśnienie:

q        read the input
{…}fC    for each character C in the input
  "…"    push that long string, containing code to handle various cases
  35/    split it into (two) parts of length 35
  T=     get the T'th part; T is 1 when parsing a string and 0 otherwise
          (T is initially 0 by default)
  S/     split by space into an array of strings
  (      take out the first item (containing special characters to check)
  C#     find the index of C in that string
  =      get the corresponding string from the array
          (when C is not found, # returns -1 which gets the last array item)
  ~      execute that string

Teraz długi ciąg z różnymi fragmentami kodu. Każda część ma kilka znaków do sprawdzenia, a następnie blok do obsługi każdej z nich oraz domyślny przypadek.

Pierwsza część: Slt 1:T;L ]',*'[\+']+ ]',*'(\+')+ [

Slt      special characters to check
######## first block, corresponding to character 'S'
1:T;     set T=1, causing the next characters to be processed with the 2nd part
L        push an empty string/array, which will be used to collect the string
######## second block, corresponding to character 'l'
]        end array
',*      join with commas
'[\+     prepend a '['
']+      append a ']'
######## third block, corresponding to character 't'
]        end array
',*      join with commas
'(\+     prepend a '('
')+      append a ')'
######## last block, corresponding to other characters (practically, '(' and '.')
[        start array

Druga część: (newline) 0:T; C+

newline  special characters to check (only one)
######## first block, corresponding to newline
0:T;     set T=0, switching back to the first part
######## last block, corresponding to any other character (including apostrophe)
C+       append the character to the collecting string
aditsu
źródło
3

Perl, 149 bajtów

Mam złe przeczucie, że to kiepska próba, ale oto:

$/=$,;$"=",";@s=[];/^\(/?$s[@s]=[]:{$p=/S(.*')/?$1:/l|t/?($l="@{pop@s}")|/l/?"[$l]":"($l)":0,push@{$s[-1]},$p}for<>=~/([(lt]|S.*?\n)/g;print$s[0][0];

Skrypt musi zostać zapisany w pliku i pobiera dane wejściowe z STDIN.

Wyjaśnienie:

# Set the input record separator to undef so that <> reads all lines at
# once
$/=$,;
# Ensure that elements of lists printed in quotes are separated by commas
$"=",";

# The stack. Initialise the bottom element with an empty array
@s=[];

# Tokens are extracted in the for loop a few lines below. Copied here for
# clarity: Read the entire input and iterate over all valid tokens of the
# pickle language
# for <>=~/([(lt]|S.*?\n)/g;
# the token is a mark - push an empty array to the stack
/^\(/ ? $s[@s]=[]
      # token is a string, push it inside the stack top
      : {$p=/S(.*')/ ? $1
                     # otherwise, remove the top and create list or tuple
                     # from it and push it inside the top element
                     : /l|t/ ? ($l="@{pop@s}") | /l/ ? "[$l]"
                                                     : "($l)"
                             : 0 # dummy value
                             # pushing of the string/list/tuple actually
                             # happens here
                             , push@{$s[-1]},$p} 
# read the entire input at once and iterate over all valid tokens
for <>=~/([(lt]|S.*?\n)/g;

# in the end, the bottom element of the stack will be an array with just one
# element which is the string representation of the object
print$s[0][0];
svsd
źródło
0

> <>, 88 bajtów

^"][">}r]
~rl?!;o11.
^0\!\
 &</\?[1&~?=1l","
 1/\ii:"'"=?v44.
>i9%0$.     >r]i~


 ")("\

Zabawa ze skokami! Wykorzystuje fakt, że kody ASCII dla 5 głównych zaangażowanych poleceń, mod 9, to:

S -> 2
l -> 0
t -> 8
( -> 4
. -> 1

Dzięki temu każda operacja może być obsługiwana na osobnej linii, do której nastąpi bezpośrednie przejście. Wykorzystuje również stosy do konstruowania każdego łańcucha i zagnieżdżonej listy / krotki osobno przed zawinięciem ich w wymagane znaki.

Sok
źródło
Dobra robota, ale niestety wydaje mi się, że nie otrzymuję właściwego wyniku dla większości przypadków testowych (po pierwsze, nawiasy wydają się być niewłaściwe)
Sp3000,
0

JavaScript (ES6), 199 bajtów

s=>(q=x=>(o=[],x.slice(0,-1).map(v=>o=[...o,v.map?q(v):`'${v}'`]),x.pop()<"m"?`[${o}]`:`(${o})`),q(eval(s[r="replace"](/\(/g,"[")[r](/[tl](?![\w ]+'\n)/g,"'$&'],")[r](/S('.+')/g,"$1,").slice(0,-2))))

Uruchamia kilka wyrażeń regularnych na wejściu, aby przekształcić go w poprawny kod JS, a następnie analizuje.

Test Snippet

f=
s=>(q=x=>(o=[],x.slice(0,-1).map(v=>o=[...o,v.map?q(v):`'${v}'`]),x.pop()<"m"?`[${o}]`:`(${o})`),q(eval(s[r="replace"](/\(/g,"[")[r](/[tl](?![\w ]*'\n)/g,"'$&'],")[r](/S('.+')/g,"$1,").slice(0,-2))))
<select oninput="I.value=this.selectedIndex?this.value.replace(/\\n/g,'\n'):'';O.innerHTML=this.selectedIndex?f(I.value):''"><option>---Tests---<option>(l.<option>(t.</option><option>(S'hello world'\nl.<option>(S'string one'\nS'string two'\nS'string three'\nt.<option>(S'a'\n(S'b'\nS'c'\nlt.<option>((S'a'\nS'b'\n(lS'c'\nt(S'd'\ntl.<option>((S'a'\n((S'b'\nt(S'c'\nlS'd'\n(((ltlS'e'\nS'f'\nlS'g'\ntl.</select><br>
<textarea rows=10 cols=20 id=I></textarea><br><button onclick="O.innerHTML=f(I.value)">Run</button><br><pre id=O></pre>

Justin Mariner
źródło
0

Julia + ParserCombinator.jl 306 240

Dzięki najnowszemu zestawowi poprawek nie sądzę, że rozwiązanie z czystą Julią byłoby krótsze.

using ParserCombinator
v=join
j(t)=v(t,",")
a=Delayed()
s=E"S'"+Star(p".")+Drop(Equal("'\n"))|>x->"'$(v(x))'"
i=Star(a)|E""
l=E"("+i+E"l"|>x->"[$(j(x))]"
t=E"("+i+E"t"|>x->"($(j(x)))"
a.matcher=s|l|t
f(x)=parse_one(x,a+E".")|>first

To było interesujące. Myślę, że kodowany jest dość elokwentny.

  • Formatowanie wyjściowe odbywa się przy generowaniu
  • a l, i, t, I ssą w zasadzie cfg zasady
  • f nazywana jest funkcją, która łączy wszystko razem.
  • Drop(Equal("'\n"))jest irytujące - że najlepiej być zapisany jako E"\n"ale Emakro łańcuch nie obsługuje sekwencje.
  • Interesujące jest to można trywialny przekształcone na powrót Julia struktur danych, to jest w zasadzie usuwania transformaty na RHS z |>s i dodając tupledo treguły
Lyndon White
źródło
Niestety, zgodnie z zasadami w naszym centrum pomocy , gra w golfa jest wymagana do publikowania rozwiązań problemów związanych z golfem.
Dennis
Nie jestem jednak w 100% zdolny do zrobienia krótszego. Jest to gra w golfa do tego stopnia, że ​​każde rozwiązanie wykorzystujące tę kombinację języka / biblioteki „Julia + ParserCombinator.jl” może być gra w golfa. Ale z drugiej strony istnieje zasadnicza zmiana, że ​​istnieje krótsze rozwiązanie z czystą Julią ... teraz muszę to napisać.
Lyndon White
Nie musisz pisać zupełnie innego rozwiązania; wystarczy maksymalnie wykorzystać swoje podejście. Przynajmniej komentarze powinny zostać usunięte.
Dennis
Nie policzyłem komentarzy (ani pustych wierszy) do liczby bajtów. Uznałem, że to konwencja, chyba źle zrozumiałem
Lyndon White
Tak, kod jest oceniany jako opublikowany . Zawsze możesz jednak dodać wersję bez oznaczenia / adnotacji.
Dennis