Crie um intérprete para uma linguagem falsa baseada em pilha que obtém uma entrada, interpreta e gera o resultado como uma matriz de números. Ele deve percorrer cada byte e executar uma função diferente com base nesta tabela:
0000 (0): Concatenar (combine os dois primeiros números de uma pilha como se fossem uma sequência. Ex: 12,5 -> 125)
0001 (1): Incremento (adicione 1 ao número na parte superior da pilha)
0010 (2): Decremento (Subtraia um do número na parte superior da pilha)
0011 (3): Multiplique (Multiplique os dois números superiores na pilha)
0100 (4): Divida (Divida o número do 2º ao topo por o número superior na pilha)
0101 (5): Adicionar (adicionar os dois números superiores na pilha)
0110 (6): Subtrair (subtrair o número superior na pilha do número abaixo)
0111 (7): expoente ( Calcule o número do segundo ao topo com a potência do número superior)
1000 (8): Módulo: (Encontre o número do segundo ao topo no módulo)
1001 (9): Gire para a direita (mude a pilha para baixo um. O número na parte inferior agora está no topo)
1010 (A): Gire para a esquerda (mude a pilha para cima um. O número na parte superior agora está no fundo)
1011 (B): duplicado (copie o número superior para que apareça duas vezes. Ex: 4,1 torna-se 4,1,1)
1100 (C): duplicado duplo (copie os dois números superiores na pilha. Ex: 4, 1,2 torna-se 4,1,2,1,2)
1101 (D): Troque (troque os dois primeiros números da pilha. Ex: 4,1,2 torna-se 4,2,1)
1110 (E): Dobro Trocar (troque os dois primeiros números com os dois abaixo deles.ex: 1,2,3,4,5 torna-se 1,4,5,2,3)
1111 (F): Excluir / Pop (Remova o número na parte superior de a pilha)
Por exemplo, um arquivo contendo
1 1 BC 5 C 5 B 9 5 - Entrada (hex) | | | | | | | | | | 1 2 2 2 4 4 6 6 2 8 - Pilha 2 2 2 2 4 6 6 6 2 2 4 2 4 6 4 2 2 2 2 4 2 2 2 2
produziria [8,6,4,2]
Regras:
- Unicode / símbolos estão bem, mas ASCII é melhor.
- Seja criativo! A falta é importante, mas a criatividade é ótima!
- Se os bytes forem muito difíceis, use
"$iv*/+-^%><dtsz."
ou em"0123456789ABCDEF"
vez dos bytes reais. - RAPIDEZ! Quanto mais rápido, melhor.
- A pontuação é baseada na reputação, mas o tamanho é um fator enorme.
Bônus:
Tente concluir esse desafio usando o intérprete recém-criado com o menor número possível de strings.
Nota:
O que torna esse desafio desafiador ao contrário de outros desafios do código de golfe é que não há código para seguir adiante. Se, digamos, você tivesse que escrever um intérprete cerebral, você poderia observar as implementações de outras pessoas. Com isso, você não pode fazer isso.
Eu esqueci de colocar e data final sobre isso. Acho que vou fazer daqui a um mês a partir da data em que criei isso. A pessoa com os maiores votos em 22 de fevereiro vence!
fonte
Respostas:
Ruby, 67 linhas de substituições regex
Decidi escrever o intérprete em regex, enquanto seguia algoritmos eficientes.
Eu poderia ter optado por bytes simples, mas o uso de símbolos torna o código mais legível na minha opinião. Claro, se pudéssemos embalar duas instruções em um byte ...
A concatenação de valores negativos resulta no comportamento do complemento de dez, refletindo a representação interna.
Divisão é divisão inteira e o restante nunca é negativo.
Quanto à rodada de bônus, a solução mais curta que encontrei ( 13 caracteres ) é uma solução limpa:
fonte
d
(depoisii
, a pilha contém apenas2
, nada para trocar), e a final gira (bem, pelo menos a primeira, a segunda é apenas uma troca disfarçada ... ) deve estar à esquerda, não à direita.montagem x86 (no Win32)
"VELOCIDADE!" Parece ser extremamente importante aqui, e todos sabemos que nada supera a linguagem assembly a esse respeito. Então, vamos fazer isso em montagem!
Esta é uma implementação do idioma na linguagem assembly x86 (na sintaxe NASM), com os números armazenados e interpretados como números inteiros de 32 bits não assinados, usando diretamente a pilha nativa x86. O estouro de pilha e estouro durante qualquer operação aritmética (ou divisão por zero) é um erro de tempo de execução, finalizando o programa com uma mensagem de erro.
Para compilar isso, use algo como
O programa recebe o nome do arquivo binário que contém o programa na linha de comando (por exemplo
nexlang.exe testprg.bin
). Quando concluído, imprime o conteúdo final da pilha na saída padrão em um formato legível por humanos.Para ajudar no teste, salve o seguinte em
nex.def
:E, em seguida, escreva seus programas NEX ("inexistentes", conforme nomeados no título da pergunta) usando as mnemônicas definidas acima e compile com algo como
Por exemplo, para o caso de teste original, use o seguinte
prg.nex
:E, finalmente, para o desafio "2014", use o seguinte programa NEX de 14 bytes:
fonte
LEA ESI, [ESI+1]
que ao invés deINC ESI
?GolfScript, 64 caracteres
OK, então eu decidi tentar jogar isso. E que linguagem melhor para o golfe do que o GolfScript?
Convenientemente, o próprio GolfScript já é uma linguagem baseada em pilha com comandos de byte único e, por acaso, 11 dos 16 comandos são mapeados diretamente para os comandos internos do GolfScript. Então, tudo o que realmente preciso fazer para interpretar sua linguagem é implementar os cinco comandos restantes no GolfScript e criar uma tabela de tradução:
O código parece meio espalhado, porque estou usando novas linhas como delimitadores para a tabela de tradução. A inicial
0\
coloca um zero na pilha e a move abaixo do programa de entrada. O{ }/
loop, que compreende a maior parte do código, retira o programa de entrada da pilha e itera o corpo do loop sobre cada um de seus caracteres, e o final]-1%`
coleta a pilha em uma matriz, reverte-a (porque sua saída de amostra começa na parte superior do pilha) e o especifica.O corpo do loop começa com uma seqüência de 16 linhas entre aspas simples.
n%
divide essa sequência em quebras de linha,=
procura a substring correspondente ao caractere de entrada e~
avalia a substring como código GolfScript.Finalmente, aqui estão as implementações do GolfScript dos 16 comandos:
`+~
: concatena dois números como cadeias)
: incremento(
: decremento*
: multiplicar/
: dividir+
: adicionar-
: subtrair?
: elevar ao poder%
: módulo](+~
: gira a pilha para a direita])\~
: gira a pilha para a esquerda.
: duplicado1$1$
: duplicado duplo\
: troca[@]\+~\
: troca dupla;
: popEstou meio descontente com a troca dupla - é feio e muito mais longo do que qualquer outro comando. Parece que deveria haver uma maneira melhor, mas se sim, ainda não a encontrei. Ainda assim, pelo menos funciona.
Por exemplo, executando o programa acima na entrada (fornecida como uma sequência de aspas duplas GolfScript / Ruby / Perl / Python / etc.):
produz a saída:
Edit: Consegui salvar mais dois caracteres, para um total de 62 caracteres , usando uma codificação mais compacta da tabela de tradução. No entanto, isso meio que sacrifica a legibilidade:
Os recursos notáveis desta versão incluem o
(
no início do loop, que muda os índices de comando de 0..15 para -1..14, para que eu possa colocar a longa sequência de comandos de caractere único de 1 a 8 no início da mesa. Isso me permite armazená-los em uma sequência separada e eliminar as oito novas linhas que os delimitam; infelizmente, a complexidade extra me custa seis caracteres em outros lugares.fonte
+
em])\+~
Haskell
Por diversão, criei uma solução que não utiliza variáveis , apenas combina funções.
fonte
Ruby,
330316 caracteresEu decidi jogar golfe. (Porque isso é sempre divertido.)
A parte principal é esta:
Ele converte cada dígito hexadecimal em um número inteiro de base 10 e, em seguida, usa o
[(huge array of strings)]
para encontrar a sequência correta que representa esse comando. Entãoeval
é essa corda.Note que
%w[x y z]
é equivalente a['x','y','z']
.Eu também gosto de como você pode encontrar carinhas felizes nessa linha! Alguns deles são
:*
:/
:-]
:%
Exemplo de execução:
fonte
C -
642634 caracteresApenas para o
$iv*/+-^%><dtsz.
dialeto (adicionaq
como um caractere final, junto com0
):Solução para o desafio de 2014:
dididiizs>
.fonte
free(a);
. E não deveria estar<<2
nasrealloc
ligações?free()
memória: Pk, 228
Há uma quantidade razoável de repetições na implementação de instruções semelhantes, que provavelmente podem ser projetadas até certo ponto.
fonte
C
924882622603587569562 caracteresCom novas linhas óbvias removidas (mantidas para facilitar a leitura).
Isso implementa a interpretação "underflow push zero" do comentário de Jan Dvorak.
A versão golfada realmente mudou substancialmente em comparação com a versão não golfada aqui, sob a pressão (bem-vinda) de da boa resposta Oberon .
Descobri que substituir a
switch
declaração em favor de uma cadeiaif
...else
me permitiu fatorar todos os dígitos dos meus casos . Em vez disso, inicializa aw
variável para 47, para que um incremento a eleve para 48 (== ascii'0'
) e, em seguida, cada caso é incrementadow
até precisarmos pular para o'A'
ponto em que usamos o primeiro argumento de macro quase vazio, que adiciona 7 extras para levantar para 'A'. A versão ungolfed não mostrar o meu favoritosbrk
/SIGSEGV
truque para obter memória "livre" sem maiores alocações.fonte
log
nem está definido.R, 428 caracteres
Com recuos:
Em ação:
fonte
JavaScript, 685
Versão sem golfe ( essência ):
Versão Golfed:
Exemplo:
fonte
Haskell
Corrida
fonte
tr
?), Isso se tornará possível.Lisp comum - 589
Aceita entrada hexadecimal sem espaços.
Ungolfed:
fonte
PHP
não é a mais bonita, mas funciona.
é executado a partir do shell, espera um nome de arquivo como primeiro argumento. aceita qualquer um dos 3 dialetos (mesmo misturados)
comportamento não definido para negativos ou índice ausente
fonte
PureBasic -
2821891 caracteresEste é um intérprete interativo - nenhum arquivo, basta digitar os códigos de 0 a 9, AF, e ele executará esse comando e será exibido como a postagem de exemplo o exibe.
Use "X" ou "Q" para sair.
Isso foi realmente divertido de fazer :)
edit: Depois de dormir, imaginei jogar golfe - deixei a versão legível para referência.
Tudo funciona da mesma maneira, exceto que eu retirei o Q ou X para sair, basta fechar a janela para sair:
fonte
Lisp comum - 586
Ungolfed
Vincula Lexically uma pilha nova no código expandido por macro: nenhuma referência a uma variável global. Além disso, é compilado no código da máquina.
Exemplo
fonte
Python 2, 508 bytes
Usa a codificação "0123456789ABCDEF". Estou realmente orgulhoso de como este acabou. Ele não lê o arquivo, obtém informações do STDIN, mas se for um problema, ele pode ser facilmente alterado.
2 soluções para o problema de 2014:
B11CB3A1AED0A00
(1615 bytes) - Concatenador genérico.BB102CD11B513B3622E
(2019 bytes) - Muito mais frio - Avalia até (5 * (10-1)) ^ 2-11fonte
Python 2, 955 bytes
O que cada função faz
fonte