Un poco de pepinillo

19

El módulo pickle de Python se utiliza para la serialización, lo que permite volcar un objeto de tal manera que luego pueda reconstruirse. Para esto, pickle usa un lenguaje simple basado en la pila.

Para simplificar las cosas, trataremos con un pequeño subconjunto de este lenguaje:

(              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

Su tarea es implementar este subconjunto del lenguaje. Tenga en cuenta que aquí \nhay una nueva línea literal, y las nuevas líneas son realmente importantes para el idioma.

Para aquellos familiarizados con los lenguajes similares a GolfScript o CJam, (y l/tfuncionan de manera similar a [y ]respectivamente.

Entrada

Para mantener las cosas simples, la entrada siempre será válida. En particular, puede asumir lo siguiente sobre la entrada:

  • Las cadenas solo consistirán en letras minúsculas y espacios [a-z ], y siempre usarán comillas simples.
  • No habrá caracteres extraños, con todas las instrucciones como se especificó anteriormente. Por ejemplo, esto significa que las nuevas líneas solo ocurrirán después de las cadenas.
  • Todos l/ttienen una coincidencia (antes y todos (tienen una coincidencia l/tdespués. También habrá al menos uno (.
  • Habrá exactamente uno ., y siempre será el personaje final.

Puede tomar la entrada a través de la línea de comando, STDIN o argumento de función. Si lo desea, puede usar una sola cadena de escape de nueva línea en lugar de una cadena multilínea, pero especifique esto en su respuesta.

Salida

El resultado debe ser una representación del objeto final, impreso en STDOUT o devuelto como una cadena . Específicamente:

  • Las cadenas se representan abriendo y cerrando comillas simples con contenido intermedio, por ejemplo S'abc' -> 'abc'. No puede usar comillas dobles para este desafío, aunque estén permitidas en Python.

  • Las listas están representadas por elementos separados por comas rodeados por []( por ejemplo ['a','b','c']), mientras que las tuplas están representadas por elementos separados por comas rodeados por ()( por ejemplo ('a','b','c')).

  • Los espacios no importan, por ejemplo, ('a', 'b', 'c' )está bien.
  • No puede tener una coma antes del corchete de cierre. Tenga en cuenta que esto es intencionalmente diferente de las reglas de sintaxis de Python para facilitar las cosas para la mayoría de los lenguajes, y también para dificultar simplemente construir la lista / tupla en Python y luego generarla, debido a cómo se representa la tupla de un solo elemento (para esto desafío, necesitamos ('a')en lugar de ('a',)).

Ejemplos

El texto anterior puede parecer desalentador, pero los siguientes ejemplos deberían aclarar un poco las cosas.

(l.

Salida posible: []

(t.

Salida posible: ()

(S'hello world'
l.

Salida posible: ['hello world']

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

Salida posible: ('string one', 'string two', 'string three')

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

Salida posible: ('a',['b','c'])

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

Salida posible: [('a', 'b', [], 'c'), ('d')]

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

Salida posible: [('a',[('b'),['c'],'d',[([])],'e','f'],'g')]

Reglas

  • Este es el , por lo que gana el código en la menor cantidad de bytes.
  • No se permite ninguna funcionalidad diseñada para trabajar con pepinillos en Python.

Nota de seguridad: en el código real, solo desconéctelo de las fuentes en las que confía, de lo contrario, podría recibir una desagradable cos\nsystem\n(S'rm -rf'\ntR.sorpresa

Sp3000
fuente
¿ S'abc'\nEmpuja abco 'abc'?
CalculatorFeline

Respuestas:

4

CJam, 63

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

Pruébalo en línea

Explicación:

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

Ahora la larga cadena con varias piezas de código. Cada parte tiene algunos caracteres para verificar y luego un bloque para manejar cada uno, y el caso predeterminado.

Primera parte: 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

Segunda parte: (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
fuente
3

Perl, 149 bytes

Tengo el mal presentimiento de que este es un intento pobre, pero aquí va:

$/=$,;$"=",";@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];

La secuencia de comandos debe guardarse en un archivo y toma la entrada de STDIN.

Explicación:

# 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
fuente
0

> <>, 88 bytes

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


 ")("\

Diversión con saltos! Utiliza el hecho de que los códigos ASCII para los 5 comandos principales involucrados, mod 9, son:

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

Esto permite que cada operación se maneje en su propia línea, a la que se saltará directamente. También usa la pila de pilas para construir cada cadena y lista / tupla anidada por separado antes de envolverlas en los caracteres requeridos.

Sok
fuente
Buen trabajo, pero desafortunadamente no parece estar obteniendo la salida correcta para la mayoría de los casos de prueba (los paréntesis parecen estar al revés, por un lado)
Sp3000
0

JavaScript (ES6), 199 bytes

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))))

Ejecuta varios reemplazos de expresiones regulares en la entrada para convertirlo en un código JS válido, luego lo analiza.

Fragmento de prueba

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
fuente
0

Julia + ParserCombinator.jl 306 240

Con mi último conjunto de revisiones, ya no creo que una solución pura de Julia sea más corta.

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

Eso fue interesante. Creo que el código es bastante elocuente.

  • El formateo de salida se realiza en la generación
  • a l, i, t, Y sson, básicamente, CFG reglas
  • f es la función que se llama, lo reúne todo.
  • esto Drop(Equal("'\n"))es molesto: idealmente se escribiría como, E"\n"pero la Emacro de cadena no maneja secuencias de escape.
  • Curiosamente, esto se puede convertir trivialmente en estructuras de datos de julia devueltas, básicamente elimina las transformaciones en el RHS de |>sy agrega tuplepara la tregla
Lyndon White
fuente
Desafortunadamente, según las reglas de nuestro centro de ayuda , el golf es un requisito para publicar soluciones para codificar los desafíos del golf.
Dennis
Sin embargo, no estoy 100%, puedo hacer uno más corto. Esto se refleja hasta el punto de que cualquier solución que use esta combinación de lenguaje / biblioteca "Julia + ParserCombinator.jl" puede ser mejorada. Pero por otro lado, hay un cambio sólido de que hay una solución de julia pura más corta ... ahora tengo que escribirla.
Lyndon White
No tiene que escribir una solución completamente diferente; sacar el máximo provecho de su enfoque es suficiente. Sin embargo, al menos los comentarios deberían eliminarse.
Dennis
No conté los comentarios (o líneas en blanco) hacia el conteo de bytes. Supuse que era una convención, supongo que pensé mal
Lyndon White
Sí, el código se califica como publicado . Sin embargo, siempre puede agregar una versión anómala / anotada.
Dennis