Intérprete de golf simple


13

Desafío:

Su trabajo es crear un intérprete simple para un lenguaje de golf simple.


Entrada:

La entrada será en forma de cadena separada por espacios.

Puedes reemplazar la separación del espacio con lo que quieras


Salida:

Salida del resultado (un número o una cadena) obtenido después de realizar todas las operaciones. Si hay más de una salida, únanse para dar un solo resultado (sin separadores). El valor inicial de la variable siempre es cero. es decir: comienza en0


Sintaxis del lenguaje:

El lenguaje tiene los siguientes operadores:

inc  ---> add one to variable
dec  ---> remove one from variable
mult ---> multiply variable by 2
half ---> divide the variable by 2
Pri  ---> print the variable to console (or whatever your language has)
exit ---> end the program (anything after this is ignored)

Ejemplos:

inc inc inc dec Pri exit                 ---> 2
dec inc mult inc inc Pri                 ---> 2
inc inc inc mult half Pri exit inc       ---> 3
inc Pri inc Pri inc Pri exit half mult   ---> 123
Pri exit                                 ---> 0
inc half Pri exit                        ---> 0.5 

Restricción:

Este es el código de golf, por lo que el código más corto en bytes para cada idioma ganará.


Nota:

  • La entrada siempre será válida. (cadena de operadores separados con espacio)
  • Puede redondear hacia abajo al entero más cercano si no desea lugares decimales.

3
¿Puedo tomar una lista de cadenas? ¿Puedo usar otra capitalización?
user202729

Añadir caso de salida? la salida debería importar
l4m2 el

1
@Kaldo: Puedes separar usando nuevas líneas
Muhammad Salman

3
Hmm, no llamaría a ese lenguaje "lenguaje de golf".
Paŭlo Ebermann

1
Este es Deadfish con nombres de comando doble y medio en lugar de cuadrado y más largo
Jo King

Respuestas:


8

Bash , 61 bytes

sed '1i0
s/.//2g;y"idmhe"+-*/q";/+\|-/i1
/*\|\//i2
/P/cdn'|dc

Pruébalo en línea!

Convierte el programa en un programa de CC, luego lo evalúa como código de CC. Esto toma la entrada separada por nuevas líneas. Tenga en cuenta que dc se basa en la pila y utiliza la notación de pulido inverso.

La entrada se canaliza primero a sed

1i0 en la primera línea de entrada, inserte (anteponga) un 0, este será el acumulador

s/.//2g eliminar todo menos el primer caracter de cada línea

y"idmhe"+-*/q" transcribir idmhe en +-*/q, respectivamente, + - * / son los comandos aritméticos y q sale del programa

/+\|-/en cada línea que contenga + o -, i1inserte un 1

/*\|\// en cada línea que contiene * o /, i2 inserte un 2

/P/ en cada línea que contiene P, cdn cámbielo a dn, equivalente a duplicado y salida sin nueva línea en cc

Ahora esto se evalúa como una expresión de CC.


2
Supongo que no es irracional esperar que la sedsintaxis se vuelva aún más extraña de lo que se creía posible cuando el golf entra en juego.
Mateen Ulhaq

6

Jalea , 21 bytes

ḲḢ€O%11ị⁾’‘j“IȮḤH”¤VI

Pruébalo en línea!


Tenga en cuenta que los valores ASCII de los primeros caracteres ( idmhPe) módulo 11 son únicos módulo 6.


Usando el módulo 16:

Jalea , 21 bytes

ḲḢ€O%⁴ị“ḢwġḞkz’ṃØJ¤VI

Pruébalo en línea!

La cadena que se utiliza para indexar es ḤH‘’IȮen este caso. El ‘’ya no está en los límites.


Usar 11 bytes para representar una cadena de 6 bytes es ... demasiado malo. Pero ... “”toma 2 bytes, ¤toma 1 byte, los datos en sí mismos toman 6 bytes, quedan 2 bytes para hacer algo. Actualmente es y j, pero ịØJo ṃØJes mucho peor, y no funciona (porque Unicode).
user202729

El concepto de cadena de jli ("Una cadena es una lista de enteros con una bandera especial para afectar la impresión") es genial.
user202729

5

R , 128125 bytes

Reduce(function(x,y)switch(y,i=x+1,d=x-1,m=x*2,h=x/2,P={cat(x);x}),substr(el(strsplit(gsub("e.*$","",scan(,""))," ")),1,1),0)

Pruébalo en línea!

Se debe llamar con source(echo=FALSE)para evitar que el valor de retorno se imprima automáticamente. La alternativa sería envolver todo,invisible pero eso es mucho menos golfista (y arruina mi [todavía] buen número de bytes).


3

05AB1E , 25 bytes

΀¬"idmhPe"S"><·;=q"S‡J.V

Pruébalo en línea!

Asigna cada una de las funciones del lenguaje con la función 05AB1E correspondiente (utilizando el primer carácter de cada función) y luego ejecuta la cadena resultante como código 05AB1E.


2

Rojo , 121 bytes

func[s][v: 0 parse s[any[["i"(v: v + 1)|"d"(v: v - 1)|"m"(v: v * 2)|"h"(v: v / 2.0)|"P"(prin v)|"e"(exit)]thru" "| end]]]

Pruébalo en línea!

Legible:

f: func [s] [
    v: 0
    parse s [
        any [
            [ "i" (v: v + 1)
            | "d" (v: v - 1)
            | "m" (v: v * 2)
            | "h" (v: v / 2.0)
            | "P" (prin v)
            | "e" (exit)]
            thru [" " | end]
        ]
    ]
] 

2

Python 2 , 131 125 122 121 118 117 115 bytes

v=0;o=""
for x in input().split("x")[0].split():
 if"Q">x:o+=`v`
 else:v+=(1,-1,v,-v/2.)['idmh'.find(x[0])]
print o

Pruébalo en línea!

-6 y -3 gracias a @Rod

-3 y -2 con gracias a @etene

-1 reemplazando "Pri"==xcon"P"in x


se puede spliten "exit"y obtener la primera cuadra, en lugar breaking ahorro de 4 bytes
Rod

1
Puede eliminar los paréntesis alrededor 'idmh'y usar finden lugar de index, que va a ahorrar unos pocos bytes
ETENE

@ Rod - en realidad puede llevar eso un poco más allá y dividirse expara salvar otros 2
ElPedro

Puede reemplazar v=(v+1,v-1,v*2,v/2.)con v+=(1,-1,v,-v/2.)él debería funcionar, aunque no lo probé
Rod

@Rod: pensé en eso pero no pude averiguar cómo hacerlo half. ¡Tan sencillo! Gracias.
ElPedro

2

Python 3 , 110 91 82 bytes

exit hará que el programa salga con un error.

x=0
for c in input():c=='P'==print(x,end='');x+=(1,-1,x,-x/2,c,0)['ndmhx'.find(c)]

Pruébalo en línea!


Acorte los nombres de sus variables para guardar 9 bytes. i='x+=1';d='x-=1';...y luego en su execllamada, cámbielo aexec(eval(c[0]))
mypetlion

@mypetlion Gracias, pero encontré una mejor manera.
mbomb007

Creo que esto es válido: 82 bytes
Lynn

@ Lynn ¡Eso es genial! ¡No podría pensar en una buena forma de cortocircuito a la printdeclaración!
mbomb007

2

JavaScript (ES6), 83 79 bytes

Guardado 4 bytes gracias a @ l4m2

Iterativamente reemplaza las instrucciones con la salida o cadenas vacías.

s=>s.replace(/\S+./g,w=>m<s?'':w<{}?m:(m+={d:-1,e:w,i:1,m}[w[0]]||-m/2,''),m=0)

Pruébalo en línea!

Comentado

s =>                       // given the input string s
  s.replace(/\S+./g, w =>  // for each word w in s:
    m < s ?                //   if m is a string:
      ''                   //     ignore this instruction
    :                      //   else:
      w < {} ?             //     if w is 'Pri' ({} is coerced to '[object Object]'):
        m                  //       output the current value of m
      : (                  //     else:
          m +=             //       add to m:
            { d: -1,       //         -1 if w is 'dec'
              e: w,        //         w  if w is 'exit' (which turns m into a string)
              i: 1,        //         1  if w is 'inc'
              m            //         m  if w is 'mult'
            }[w[0]]        //       using the first character of w to decide
            || -m / 2,     //       or add -m/2 (for 'half') if the above result was falsy
        ''),               //       do not output anything
    m = 0                  //   m = unique register of our mighty CPU, initialized to 0
  )                        // end of replace()

s=>s.replace(/\S+./g,w=>k<s?'':w<{}?k:(k+={d:-1,e:w,i:1,m:k}[w[0]]||-k/2,''),k=0)
l4m2

@ l4m2 Esto w<{}es puro mal: p
Arnauld

s=>s.replace(/\S+./g,e=>m<s?'':e<{}?m:(m+={d:-1,e,i:1,m}[e[0]]||-m/2,''),m=0)también funciona
l4m2

2

Carbón , 37 35 bytes

≔⁰ηF⎇№θx…θ⌕θxθ≡ιn≦⊕ηd≦⊖ηm≦⊗ηh≦⊘ηrIη

Pruébalo en línea! El enlace es a la versión detallada del código. Inspirado por la respuesta de @ RickHitchcock. Explicación:

≔⁰η

Borrar la variable.

F⎇№θx…θ⌕θxθ≡ι

Trunca la entrada en el xcaso de que haya una, luego repite y activa cada carácter de (el resto de) la entrada.

n≦⊕η

ni n crea la variable.

d≦⊖η

d d ecrements la variable.

m≦⊗η

m m multiplica la variable por dos (es decir, dobles).

h≦⊘η

h h alves la variable.

rIη

rp r ints la variable cast a string.


1
@RickHitchcock Lo siento, no lo probé lo suficiente. Encontré una solución pero me costó un byte.
Neil

2

JavaScript (ES6), 77 75 bytes

(Prestó ( robó ) el truco de @ Arnauld de usar mcomo nombre de variable, ahorrando 2 bytes).

f=([c,...s],m=0)=>c<'x'?(c=='P'?m:'')+f(s,m+({h:-m/2,d:-1,n:1,m}[c]||0)):''

Recorre recursivamente la cadena, busca letras distintas por instrucción e ignora el resto:

  • n: inc
  • d: dec
  • m: mult
  • h: mitad
  • P: Pri
  • x: salir

Se aprovecha del hecho de que undefinedno es ni mayor que ni menos que 'x', haciendo que la recursión a tope en el extremo de la cadena o cuando se encuentra con el 'x'en la salida .


1
Después de su comentario eliminado al que, por supuesto, ya no puedo responder, olvidé pegar el enlace al código corregido (¡oh!) Pero de todos modos encontré un nuevo enfoque que es 2 bytes más corto que mi intento original.
Neil



1

JavaScript, 107 bytes

s=>eval('x=0;x'+(s.split` `.map(v=>({i:"++",d:"--",m:"*=2",h:"/=2",P:";alert(x)",e:"//"})[v[0]]).join`;x`))


1

Lua, 207 bytes

s=0;n=0;for a in io.read():gmatch'.'do if s==0 then s=1;n=a=='i'and n+1 or a=='d'and n-1 or a=='m'and n*2 or a=='h'and n/2 or n;if a=='P'then print(n)elseif a=="e"then break end elseif a==' 'then s=0 end end

1

Pitón 3 , 114 110 109 116 bytes

En realidad, habría tomado dos bytes menos en Python 2 porque execes una declaración y no necesita paréntesis ...

  • Ahorró 4 bytes adicionales gracias a @ElPedro

  • Se guardó un byte adicional aprovechando el hecho de que finddevuelve -1 en caso de error, que luego se puede usar como índice

  • +7 bytes porque no había notado la regla de no líneas nuevas :(

i=0;exec(";".join("i+=1 i-=1 i*=2 i/=2 print(i,end='') exit()".split()["idmhP".find(h[0])]for h in input().split()))

Pruébalo en línea!

Asigna el primer carácter de cada palabra de entrada a un fragmento de código Python. Estos se concatenan yexec ed.

Enfoque bastante sencillo, que probablemente podría jugarse un poco más. La dificultad reside principalmente en encontrar la forma más corta entre muchas posibles ...


112 Pruébelo en línea! si tiene los comandos como una cadena separada por espacios y se divide.
ElPedro

1
110 de hecho, ya que los soportes pueden ir ¡ Pruébelo en línea!
ElPedro

Esto no da la salida correcta. La pregunta dice que debe imprimir sin separadores, por lo que necesita print(i,end=''). Ver el cuarto caso de prueba.
mbomb007

No me había dado cuenta, lo arreglaré. Gracias !
etene

@etene Comenta cuando lo hayas solucionado y eliminaré mi voto negativo.
mbomb007

1

Ruby + -na, 81 73 65 bytes

x=0;$F.map{|w|eval %w{x+=1 x-=1 1/0 $><<x x*=2 x/=2}[w.ord%11%6]}

Pruébalo en línea!

Muy claro. Para la primera letra de cada palabra, busque la cadena de comando correspondiente y evalesta. Utiliza la división de enteros y exitsarrojando a ZeroDivisionError.

-5 bytes: uso en .ord%11%6lugar de una búsqueda de cadena. El crédito va al usuario202729

-3 bytes: .ordsolo considera el primer carácter de la cadena, por lo que puedo omitir a [0].

-8 bytes: use la -abandera para dividir automáticamente la entrada, gracias a Kirill L.


1
Usted puede ahorrar aún más bytes añadiendo -ala opción de hacer el autosplit para usted, como este
Kirill L.

1

Emojicode , 270 bytes

🐖🔥🍇🍮c 0🔂j🍡💣🐕🔟 🍇🍊😛j🔤inc🔤🍇🍮c➕c 1🍉🍋😛j🔤dec🔤🍇🍮c➖c 1🍉🍋😛j🔤mult🔤🍇🍮c✖️c 2🍉🍋😛j🔤half🔤🍇🍮c➗c 2🍉🍋😛j🔤Pri🔤🍇👄🔡c 10🍉🍓🍇🍎🍉🍉🍉

Pruébalo en línea!

🐋🔡🍇
🐖🔥🍇
🍮c 0
🔂j🍡💣🐕🔟 🍇
🍊😛j🔤inc🔤🍇🍮c➕c 1🍉
🍋😛j🔤dec🔤🍇🍮c➖c 1🍉
🍋😛j🔤mult🔤🍇🍮c✖️c 2🍉
🍋😛j🔤half🔤🍇🍮c➗c 2🍉
🍋😛j🔤Pri🔤🍇👄🔡c 10🍉
🍓🍇🍎🍉🍉🍉🍉

🏁🍇
 🔥🔤inc inc inc dec Pri exit🔤
😀🔤🔤
 🔥🔤dec inc mult inc inc Pri🔤
😀🔤🔤
 🔥🔤inc inc inc mult half Pri exit inc🔤
😀🔤🔤
 🔥🔤inc Pri inc Pri inc Pri exit half mult🔤
😀🔤🔤
 🔥🔤Pri exit🔤
😀🔤🔤
 🔥🔤inc half Pri exit🔤
🍉

0

SNOBOL4 (CSNOBOL4) , 165 bytes

	P =INPUT ' exit ' 
	x =0
S	P LEN(1) $ L ARB ' ' REM . P	:S($L)F(end)
i	X =X + 1	:(S)
d	X =X - 1	:(S)
P	O =O X		:(S)
m	X =X * 2	:(S)
h	X =X / 2.	:(S)
e	OUTPUT =O
END

Pruébalo en línea!

Bruto.

	P =INPUT ' exit ' 				;* append ' exit ' to the input to guarantee that the program will stop
	x =0						;* initialize x to 0 else it won't print properly if the program is 'Pri'
S	P LEN(1) $ L ARB ' ' REM . P	:S($L)F(end)	;* set L to the first letter of the word and goto the appropriate label
i	X =X + 1	:(S)
d	X =X - 1	:(S)
P	O =O X		:(S)				;* append X to the output string
m	X =X * 2	:(S)
h	X =X / 2.	:(S)				;* divide by 2. to ensure floating point
e	OUTPUT =O					;* print whatever's in O, which starts off as ''
END

0

C # (.NET Core), 186 bytes

class P{static void Main(string[]a){int v=0;foreach(var s in a){var i=s[0];if(i=='i')v++;if(i=='d')v--;if(i=='m')v*=2;if(i=='h')v/=2;if(i=='P')System.Console.Write(v);if(i=='e')break;}}}

Puede afeitarse 26bytes fuera de esto haciendo algunas cosas simples, como declarar icon v, consultando una tabla ASCII para que pueda utilizar los números pequeños, la reordenación de la ifs, y luego usando un ternario: class Z{static void Main(string[]a){int v=0,i;foreach(var s in a){i=s[0]%'d';if(i==1)break;if(i>9)System.Console.Write(v);else v=i<1?v-1:i<5?v/2:i<6?v+1:v*2;}}}(PS una explicación de cómo funciona y cómo utilizar (por ejemplo, espera argumentos de línea de comando) siempre es apreciado)
VisualMelon

(Oh, eso es vergonzoso ... Debería haber usado en %50lugar de %'d')
VisualMelon

0

Perl 5 -a , 61 bytes

eval'$,'.qw(++ -- ;exit ;print$,||0 *=2 /=2)[(ord)%11%6]for@F

Pruébalo en línea!

@ Robó de user202729 ord%11%6truco

¿Cómo?

-a            # split the input by whitespace, store in @F
eval          # Execute the string that results from:
'$,'          # $, (the accumulator)
.             # appending:
qw(           # create an array for the following whitespace separated values:
++ --            # operators for inc & dec
;exit            # exit
;print$,||0      # Pri  (||0 ensures that 0 is output if accumulator is null
*=2 /=2)         # mult div
[(ord)%11%6] # @user202729's trick selects one of the preceding operations
for@F        # for every term input

0

Pyth, 44 bytes

Vmx"idmhPe"hdcwd=Z@[hZtZyZcZ2ZZ)NIqN4pZIqN6B

Banco de pruebas

explicación

Vmx"idmhPe"hdcwd=Z@[hZtZyZcZ2ZZ)NIqN4pZIqN6B   ## full program
             cwd                               ## split input on space
Vmx"idmhPe"hd                                  ## iterate through list of numbers corresponding to operators
                =Z@[hZtZyZcZ2ZZ)N              ## assign the variable Z (initialliy Zero) it's new value
                                 IqN4pZ        ## print Z if the current operator is "Pri" (4)
                                       IqN6B   ## break if the current operator is "exit" (5)

0

TI-BASIC, 112 bytes

Esto aprovecha algunos supuestos que son AFAIK perfectamente aceptables. El número uno es que todas las variables se inicializan a cero antes de la ejecución; número dos es que la entrada se toma a través de Ans.

Ans+" E→Str1
While 1
I+4→I
sub(Str1,I-3,1→Str2
A+(Ans="I")-(Ans="D
If inString("MH",Str2
Then
I+1→I
2AAns+A/2(1-Ans
End
If Str2="P
Disp A
If Str2="E
Stop
Ans→A
End

0

Java (OpenJDK 8) , 164 bytes

a->{int c=0;for(String g:a.split(" ")){char b=g.charAt(0);if(b==105)c++;if(b==100)c--;if(b==109)c*=2;if(b==104)c/=2;if(b==80)System.out.print(c);if(b==101)return;}}

Pruébalo en línea!

Arriba está mi solución que se completa con números enteros, pero abajo está mi solución que maneja decimales. La forma desagradable en que las impresiones de Java se duplican agrega otros 55 byes al puntaje. Dejé las nuevas líneas para hacer que el código sea más legible en el segundo envío solo porque es esencialmente la misma solución con un comando adicional y una declaración de importación.

Java (OpenJDK 8) , 219 bytes

a->{
double c=0;
for(String g:a.split(" ")){
char b=g.charAt(0);
if(b==105)c++;
if(b==100)c--;
if(b==109)c*=2;
if(b==104)c/=2;
if(b==80)System.out.print(new DecimalFormat("0.#").format(c));
if(b==101)return;}}

Pruébalo en línea!


0

C (gcc) , 120 114 111 bytes

-6 bytes gracias a ceilingcat.

x,d;f(char*s){for(x=0;s>1;s=index(d^1?s:"",32)+1)d=*s-100,x+=d?d==5:-1,x*=d^9?d^4?1:.5:2,d+20||printf("%d",x);}

Pruébalo en línea!

124 bytes

Versión de punto flotante:

d;f(char*s){for(float f=0;s>1;s=strchr(s,32)+1)d=*s-80,f+=d==25,f-=d==20,f*=d^29?d^24?1:.5:2,s=d^21?s:"",d?:printf("%f",f);}

Pruébalo en línea!

No me molesté con una versión que se redondea, pero hace una excepción para 0, que estaría permitida, si entiendo la cadena de comentarios correctamente.


0

33 , 62 bytes

s'i'{1a}'d'{1m}'m'{2x}'h'{2d}'P'{o}'e'{@}It[mzsjk""ltqztItn1a]

Pruébalo en línea!

Este programa toma las instrucciones delimitadas por líneas nuevas

Explicación:

It[mzsjk""ltqztItn1a]
  [mz            n1a] | Forever
It    jk       It     | - Get the first character of the next instruction
            qz        | - Call the function declared previously
     s  ""lt  t       | - Make sure we don't lose track of the variable

El código antes de ese segmento define todas las funciones.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.