Intérprete de golfe simples

13

Desafio:

Seu trabalho é criar um intérprete simples para uma linguagem simples de golfe.


Entrada:

A entrada será na forma de sequência separada por espaços.

Você pode substituir a separação de espaço pelo que deseja


Resultado:

Produza o resultado (um número ou uma sequência) obtido após a execução de todas as operações. Se houver mais de uma saída, junte-se para fornecer um único resultado (sem separadores). O valor inicial da variável é sempre zero. ou seja: começa às0


Sintaxe do idioma:

O idioma possui os seguintes 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)

Exemplos:

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 

Restrição:

Este é o código-golfe, pelo que o código mais curto em bytes para cada idioma vencerá.


Nota:

  • A entrada sempre será válida. (sequência de operadores separados por espaço)
  • Você pode arredondar para o número inteiro mais próximo se não desejar casas decimais.
Muhammad Salman
fonte
3
Posso pegar uma lista de strings? Posso usar outra capitalização?
usar o seguinte comando
Adicionar caso de saída? saída deve importar
l4m2
1
@Kaldo: Você pode separar usando novas linhas
Muhammad Salman
3
Hmm, eu não chamaria essa linguagem de "linguagem do golfe".
Paŭlo Ebermann 28/04
1
Esta é Deadfish com casal e meia em vez de nomes de comandos quadrados e mais longos
Jo rei

Respostas:

8

Bash , 61 bytes

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

Experimente online!

Converte o programa em um programa dc e o avalia como código dc. Isso separa a entrada por novas linhas. Observe que dc é baseado em pilha e usa a notação de polimento reverso.

A entrada é canalizada primeiro para sed

1i0 na primeira linha de entrada, insira (prepend) um 0, este será o acumulador

s/.//2g remova tudo, exceto o primeiro caractere de cada linha

y"idmhe"+-*/q"transliterar idmhepara +-*/qrespectivamente, + - * / são os comandos aritméticos eq sai do programa

/+\|-/em todas as linhas que contêm + ou -, i1insira 1

/*\|\//em cada linha contendo * ou /, i2insira um 2

/P/em cada linha que contém P, cdnmude paradn equivalente à duplicação e saída sem nova linha em dc

Agora isso é avaliado como uma expressão dc.

Kritixi Lithos
fonte
2
Suponho que não seja razoável esperar que a sedsintaxe se torne ainda mais estranha do que se pensava ser possível quando o golfe entra em jogo.
Permita-se a falta
6

Gelatina , 21 bytes

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

Experimente online!


Observe que os valores ASCII dos primeiros caracteres ( idmhPe) módulo 11 são o módulo exclusivo 6.


Usando o módulo 16:

Gelatina , 21 bytes

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

Experimente online!

A sequência usada para indexar é ḤH‘’IȮneste caso. Não ‘’estão mais nos limites.

user202729
fonte
Usar 11 bytes para representar uma sequência de 6 bytes é ... muito ruim. Mas ... “”leva 2 bytes, ¤leva 1 byte, os dados em si levam 6 bytes, restam 2 bytes para fazer alguma coisa. Atualmente é e j, mas ịØJou ṃØJé muito pior, e não funciona (porque Unicode).
usar o seguinte comando
O conceito de string do jli ("Uma string é uma lista de números inteiros com um sinalizador especial para afetar a impressão") é excelente.
usar o seguinte comando
5

R , 128 bytes 125

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)

Experimente online!

Deve ser chamado com source(echo=FALSE)para impedir que o valor de retorno seja impresso automaticamente. A alternativa seria envolver tudo,invisible mas isso é muito menos golfe (e arruina minha [ainda] boa contagem de bytes).

Giuseppe
fonte
3

05AB1E , 25 bytes

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

Experimente online!

Mapeia cada uma das funções de idioma com a função 05AB1E correspondente (usando o primeiro caractere de cada função) e, em seguida, executa a sequência resultante como código 05AB1E.

Kaldo
fonte
2

Vermelho , 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]]]

Experimente online!

Legível:

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]
        ]
    ]
] 
Galen Ivanov
fonte
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

Experimente online!

-6 e -3 com agradecimentos a @Rod

-3 e -2 com agradecimentos a @etene

-1 substituindo "Pri"==xpor"P"in x

ElPedro
fonte
você pode splitem "exit"e obter o 1º bloco, em vez breaking salvar 4 bytes
Rod
1
Você pode remover os parênteses 'idmh'e usáfindindex
los
@Rod - pode realmente levar isso um pouco mais e dividida em expara salvar outro 2
ElPedro
Você pode substituir v=(v+1,v-1,v*2,v/2.)com v+=(1,-1,v,-v/2.)ele deve funcionar, não testada embora
Rod
@ Rod - pensei sobre isso, mas não conseguia descobrir como fazer o half. Tão simples! Obrigado.
ElPedro
2

Python 3 , 110 91 82 bytes

exit fará com que o programa saia com um erro.

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

Experimente online!

mbomb007
fonte
Reduza os nomes das variáveis ​​para economizar 9 bytes. i='x+=1';d='x-=1';...e depois na sua execligação, mude paraexec(eval(c[0]))
mypetlion
@ypetlion Obrigado, mas eu achei uma maneira melhor.
mbomb007
Eu acho que isso é válido: 82 bytes
Lynn
@ Lynn Isso é ótimo! Não consegui pensar em uma maneira agradável de causar um curto-circuito na printdeclaração!
mbomb007
2

JavaScript (ES6), 83 79 bytes

Guardado 4 bytes graças a @ l4m2

Substitui iterativamente as instruções pela saída ou pelas seqüências de caracteres vazias.

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

Experimente online!

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()
Arnauld
fonte
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 Isso w<{}é pura maldade: 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)também funciona
l4m2 28/04
2

Carvão , 37 35 bytes

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

Experimente online! Link é a versão detalhada do código. Inspirado pela resposta de @ RickHitchcock. Explicação:

≔⁰η

Limpe a variável.

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

Trunque a entrada no xse houver um, faça um loop e ligue cada caractere (o restante) da entrada.

n≦⊕η

ni n incrementa a variável.

d≦⊖η

d d cria a variável.

m≦⊗η

m m ultiplies a variável por dois (isto é, duplos).

h≦⊘η

h h alves a variável.

rIη

rp r insere a variável convertida em string.

Neil
fonte
1
@ RickHitchcock Desculpe, não testou isso o suficiente. Encontrei uma solução alternativa, mas me custou um byte.
315 Neil
2

JavaScript (ES6), 77 75 bytes

(Emprestado ( roubado ) @ O truque de Arnauld de usar mcomo o nome da variável, economizando 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)):''

Percorre recursivamente a string, procurando letras distintas por instrução e ignorando o resto:

  • n: inc
  • d: dec
  • m: mult
  • h: metade
  • P: Pri
  • x: exit

Tira proveito do fato de que undefinednão é nem maior que nem menos do que 'x', fazendo com que a recursão para parar no final da string ou quando encontra o 'x'na saída .

Rick Hitchcock
fonte
1
Após o comentário excluído ao qual é claro que não posso mais responder, esqueci de colar o link para o código corrigido (d'oh!), Mas encontrei uma nova abordagem 2 bytes mais curta que a minha tentativa original.
30518 Neil
1

JavaScript (Node.js) , 107 bytes

f=s=>s.split` `.map(([o])=>F?0:o=="i"?i++:o=="d"?i--:o=="m"?i*=2:o=="h"?i/=2:o=="P"?S+=i:F=1,F=i=0,S="")&&S

Experimente online!

DanielIndie
fonte
Isto, como é deve ser contado como 105 bytes afaik, contanto que sua função não chamar-se que você não precisa contarf=
Brian H.
1

JavaScript (Node.js) , 91 bytes

_=>_.split` `.map(o=>o<{}>!_?S+=+i:o<"e"?i--:o<"f"?++_:o<"i"?i/=2:o<"j"?i++:i*=2,i=S="")&&S

Experimente online!

JavaScript (Node.js) , 96 bytes

_=>_.split` `.map(o=>F?0:o<"Q"?S+=i:o<"e"?i--:o<"f"?F=1:o<"i"?i/=2:o<"j"?i++:i*=2,F=i=0,S="")&&S

Experimente online!

JavaScript (Node.js) , 99 bytes

s=>s.split` `.map(_=>eval('++i7--i7++e7u+=+i7i*=27i/=2'.split(7)[Buffer(e+_)[0]%11%6]),e=i=u='')&&u

Experimente online!

l4m2
fonte
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`))
Brian H.
fonte
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
Jujhar Singh
fonte
1

Python 3 , 114 110 109 116 bytes

Na verdade, seria necessário dois bytes a menos no Python 2 porque execé uma declaração e não precisa de parênteses ...

  • Guardou 4 bytes adicionais graças a @ElPedro

  • Economizou um byte extra aproveitando o fato de findretornar -1 com erro, que pode ser usado como índice

  • +7 bytes porque eu não havia notado a regra de não novas linhas :(

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

Experimente online!

Mapeia o primeiro caractere de cada palavra de entrada para um pedaço do código Python. Estes são então concatenados eexec editados.

Abordagem bastante direta, que provavelmente poderia ser um pouco mais golfe. A dificuldade reside principalmente em encontrar a forma mais curta dentre as possíveis ...

eteno
fonte
112 Experimente online! se você tiver os comandos como uma sequência separada por espaço e divida-a.
ElPedro
1
110 de fato, como os suportes podem ir Experimente-o online!
ElPedro
Isso não fornece a saída correta. A pergunta diz que você deve imprimir sem separadores, por isso precisa print(i,end=''). Veja o quarto caso de teste.
mbomb007
Eu não tinha notado, eu vou consertar. Obrigado !
Eteno # 27/18
@ etene Comente quando você o tiver corrigido e eu removerei meu voto negativo.
precisa saber é o seguinte
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]}

Experimente online!

Bem direto. Para a primeira letra de cada palavra, encontre a sequência de comandos correspondente e evalela. Usa divisão inteira e exitsjogando a ZeroDivisionError.

-5 bytes: use em .ord%11%6vez de uma pesquisa de sequência. O crédito vai para user202729

-3 bytes: .ordconsidera apenas o primeiro caractere da string, para que eu possa pular a [0].

-8 bytes: use o -asinalizador para dividir automaticamente a entrada, graças a Kirill L.

benj2240
fonte
1
Você pode economizar ainda mais bytes, adicionando -aa opção de fazer o autosplit para você, como esta
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🍉🍓🍇🍎🍉🍉🍉

Experimente online!

🐋🔡🍇
🐖🔥🍇
🍮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🔤
🍉
X1M4L
fonte
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

Experimente online!

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
Giuseppe
fonte
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;}}}
Romen
fonte
Você pode raspar 26bytes fora isso fazendo algumas coisas simples, como declarar icom v, consultando uma tabela ASCII que você pode usar números pequenos, reorganizando o ifs, e em seguida, usando um ternário: 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 uma explicação de como ele funciona e como usar -lo (por exemplo, espera args de linha de comando) é sempre apreciado)!
VisualMelon
(Oh que é embaraçoso ... Eu deveria ter uso %50em vez de %'d')
VisualMelon
0

Perl 5 -a , 61 bytes

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

Experimente online!

Roubou @ user202729 ord%11%6 truque de

Quão?

-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
Xcali
fonte
0

Pyth, 44 Bytes

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

Suíte de teste

explicação

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)
KarlKastor
fonte
0

TI-BASIC, 112 bytes

Isso tira proveito de algumas suposições que são perfeitamente aceitáveis ​​pelo AFAIK. O número um é que todas as variáveis ​​são inicializadas em zero antes da execução; número dois sendo que a entrada é obtida via 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
kamoroso94
fonte
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;}}

Experimente online!

Acima está minha solução que arredonda para números inteiros, mas abaixo está minha solução que lida com decimais. A maneira desagradável que o java imprime dobra adiciona mais 55 bytes à pontuação. Deixei as novas linhas para tornar o código mais legível no segundo envio apenas porque é essencialmente a mesma solução com um comando extra e uma declaração de importação.

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

Experimente online!

X1M4L
fonte
0

C (gcc) , 120 114 111 bytes

-6 bytes graças ao 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);}

Experimente online!

124 bytes

Versão de ponto flutuante:

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

Experimente online!

Eu não me incomodei com uma versão que arredonda para baixo, mas abre uma exceção para 0, o que seria permitido se eu entendesse a cadeia de comentários corretamente.

gastropner
fonte
0

33 , 62 bytes

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

Experimente online!

Este programa segue as instruções delimitadas por novas linhas

Explicação:

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

O código antes desse segmento define todas as funções.

TheOnlyMrCat
fonte