99 (pronunciado "noventa e nove") é uma nova linguagem de programação esotérica (não deve ser confundida com 99 , observe o itálico). Sua tarefa neste desafio é escrever um intérprete para 99 o mais curto possível. O envio com o menor número de bytes vence. O desempatador vai para a submissão postada primeiro.
Como essa pergunta é um pouco mais profunda do que o normal, e estou ansiosa para ver boas respostas, concederei uma recompensa de 250 repetições à minha resposta favorita (não necessariamente a vencedora).
99 Spec
99 é uma linguagem imperativa . Cada linha em um programa 99 é uma única instrução e, durante a execução, o ponteiro da instrução começa na linha superior e passa por cada uma das linhas subsequentes em ordem, executando-as ao longo do caminho. O programa termina quando a última linha é executada. Instruções Goto podem redirecionar o caminho do ponteiro de instruções.
Nova linha, espaço e 9
são os únicos três caracteres importantes em um programa 99 . Todos os outros caracteres são completamente ignorados. Além disso, os espaços à direita em cada linha são ignorados e vários espaços em uma linha são lidos como um espaço. ("Nova linha" refere-se a qualquer codificação de quebra de linha comum . Não importa qual o seu intérprete usa.)
Portanto, este programa:
9 BLAH 99 9a9bb9c9
9 this line and the next have 6 trailing spaces 9
É idêntico a este programa:
9 99 9999
9 9
Variáveis
Todas as variáveis em 99 têm nomes que são um ou mais 9
agrupados ( 9+
em regex). Por exemplo, 9
, 99
e 9999999999
são todas as variáveis distintas. Naturalmente, existem infinitas (exceto limitações de memória).
O valor de cada variável é um número inteiro de precisão arbitrário assinado . Por padrão, cada variável é atribuída à sua própria representação numérica. Portanto, a menos que tenha sido reatribuída, o valor da variável 9
é o número 9 e o valor da variável 99
é o número 99 e assim por diante. Você pode pensar nisso como tratar as variáveis como números simples até que sejam explicitamente atribuídas.
Usarei V
para me referir a um nome de variável arbitrário abaixo.
Cada exemplo de V
poderia ser substituída com 9
, 99
, 999
, 9999
, etc.
Afirmações
Existem cinco tipos diferentes de instruções em 99 . Cada linha em um programa 99 contém exatamente uma instrução.
A sintaxe descrita aqui assume que todos os caracteres estranhos foram removidos, todos os espaços finais foram removidos e todas as seqüências de vários espaços foram substituídas por espaços únicos.
1. Nenhuma operação
Uma linha vazia é um no-op . Não faz nada (além de aumentar o ponteiro da instrução).
2. Saída
V
Uma única variável V
em uma linha imprime essa variável em stdout.
Se V
tem um número ímpar de 9
'S ( 9
, 999
, etc), então o valor de número inteiro V
dividido por 9 será impresso (em valores decimais).
Se V
tem um número par de 9
's ( 99
, 9999
, etc), então o ASCII caracteres com código V
dividido por 9, mod 128 vai ser impressa. (Ou seja (V / 9) % 128
, um valor de 0 a 127.)
Exemplo : O programa
9
9999
iria imprimir 1W
. A primeira linha é impressa 1
porque 9/9 é 1. A segunda linha é impressa W
porque 9999/9 é 1111, e 1111 mod 128 é 87 e 87 é o código de caractere W
.
Observe que as quebras de linha não são impressas entre os tokens de saída. \n
precisa ser explicitamente impresso para uma quebra de linha.
3. Entrada
V
Uma única variável V
em uma linha com um espaço à esquerda pega a entrada do stdin e a armazena nessa variável.
Se V
tiver um número ímpar de 9
, o usuário poderá digitar qualquer número inteiro assinado e V
será definido como 9 vezes esse valor.
Se V
tiver um número par de 9
, o usuário poderá digitar qualquer caractere ASCII e V
será definido como 9 vezes seu código de caractere.
Exemplo : dado -57
e A
como entrada, este programa
9
9
99
99
iria produzir -57A
. Internamente, a variável 9
teria o valor -513 e 99
o valor 585.
Seu intérprete pode assumir que as entradas são sempre sintaticamente válidas.
4. Cessão
Essa declaração pode ser arbitrariamente longa. São duas ou mais variáveis em uma linha, separadas por espaços:
V1 V2 V3 V4 V5 ...
Isso atribui à soma de todos os 's com índices pares, menos a soma dos ' s com índices ímpares (excluindo ). As atribuições são por valor, não por referência.V1
V
V
V1
Pode ser traduzido na maioria dos idiomas como .V1 = V2 - V3 + V4 - V5 + ...
Portanto, se houver apenas duas variáveis, é uma atribuição normal:
V1 V2
→ V1 = V2
Se houver três, é subtração:
V1 V2 V3
→ V1 = V2 - V3
E o sinal +
/ -
continua alternando com cada variável adicional:
V1 V2 V3 V4
→ V1 = V2 - V3 + V4
Exemplo : Este programa produziria 1110123
:
999 Prints triple-nine divided by nine (111).
999 9 9 Assigns triple-nine to zero (nine minus nine).
999 Prints triple-nine divided by nine (0)
9 999 9 Assigns single-nine to negative nine (zero minus nine).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (1).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (2).
999 999 9 Adds nine to triple-nine (really subtracts negative nine).
999 Prints triple-nine divided by nine (3).
5. Saltar (pular se tudo zero)
Esta declaração também pode ser arbitrariamente longa. São duas ou mais variáveis em uma linha, separadas por espaços, com um espaço à esquerda :
V1 V2 V3 V4 V5 ...
Se alguns dos valores forem diferentes de zero, isso se comportará como um no-op. O ponteiro de instruções é movido para a próxima linha, como de costume.V1
Se todos os valores forem zero, o ponteiro da instrução será movido para o número da linha . As linhas são indexadas a zero, portanto, se for zero, o ponteiro se moverá para a linha superior. O programa termina (normalmente, sem erro) se for negativo ou for maior que o índice mais alto possível (número de linhas menos um).V1
V1
V1
V1
Observe que não foi dividido por 9 aqui. E como é impossível ter uma variável com um valor que não seja múltiplo de 9, apenas os números de linha com múltiplos de 9 podem ser saltados.V1
Exemplos:
Este programa imprimirá 1
para sempre:
9 Prints single-nine divided by nine (always 1).
99 9 9 Assigns double-nine to zero.
99 99 Jumps to line zero (top line) if double-nine is zero.
Este programa
99999999 Print G.
999 99 Set triple-nine to ninety-nine.
9999999999 9999999999 9999999999 99 99 9 9 999 999 Set 10-nine to zero.
99999999999 9999999999 Set 11-nine to zero.
999 Print triple-nine's value divided by nine. (This is the ninth line.)
99999999 Print G.
999 999 9 Subtract nine from triple-nine.
99999 999 Jump to line 5-nines if triple-nine is zero (ends program).
9 99999999999 9999999999 Jump to line nine if 10-nine and 11-nine are zero (always jumps).
produzirá os números 11 para 1, em ordem decrescente, cercados por G
's:
G11G10G9G8G7G6G5G4G3G2G1G
detalhes adicionais
O intérprete ideal será executado na linha de comando com o nome do arquivo do programa 99 como argumento. A E / S também será feita em tempo real na linha de comando.
Você pode, no entanto, apenas escrever uma função de intérprete que considere o programa como uma string, bem como uma lista dos tokens de entrada (por exemplo ["-57", "A"]
). A função deve imprimir ou retornar a sequência de saída.
Maneiras ligeiramente diferentes de executar o intérprete e manipular E / S são boas se essas opções forem impossíveis no seu idioma.
Bônus: escreva algo bacana em 99 e vou colocá-lo com prazer neste post como um exemplo.
- Aqui está um Pastebin de um puro programa "99 garrafas de cerveja" da resposta do Mac .