Todos nós vimos aqueles "matemáticos hax" on-line que são assim:
Think of a number, divide by 2, multiply by 0, add 8.
E, por mágica, todo mundo acaba com o número 8!
Língua
Vamos definir uma linguagem de programação que use a sintaxe do texto acima, chamada "WordMath". Os scripts do WordMath seguem este modelo:
Think of a number, <commandlist>.
O que basicamente significa: Pegue um número (como entrada de STDIN) como acumulador inicial, execute todos os comandos nele e produza o resultado.
Os comandos são separados pelo delimitador ,
(vírgula + espaço). Os comandos válidos são (observe que #
representa um número inteiro não negativo :) :
add #
/subtract #
- Adicione / subtraia o valor do acumulador.divide by #
/multiply by #
- floordiv / multiplica o acumulador pelo valor especificado.subtract from #
- Semelhante asubtract
, mas emacc = # - acc
vez deacc = acc - #
repeat
- faça o último comando novamente. Este não pode ser o 1º comando, mas você deve suportar várias repetições consecutivas.
O desafio
Sua tarefa é criar um programa ou função que use um script válido do WordMath como entrada e transpile para um programa completo válido - no mesmo idioma em que seu código está.
Por exemplo, se meu código estiver em Python 2 e o script for:
Think of a number, subtract from 10, add 10, multiply by 2.
O programa emitido pode ser:
a = input()
a = 10 - a
a += 10
a *= 2
print(a)
Ou alternativamente:
print(((10-input())+10)*2)
Desde que seja um programa completo que receba STDIN
e imprima em STDOUT
, ou nos equivalentes mais próximos do idioma.
Regras
- Seu programa original pode assumir que a entrada é sempre um script válido do WordMath.
- Os programas transpilados não precisam manipular erros matemáticos, como divisão por 0.
- Os programas transpilados podem assumir que a entrada representa um número inteiro assinado válido, dentro do intervalo inteiro padrão do seu idioma.
- Isso é código-golfe , então a solução mais curta (em bytes) vence.
- Somente a contagem de bytes do seu programa original é importante - o código emitido pode ser o tempo que você quiser!
Scripts de exemplo
Exemplo 1:
Think of a number.
Pegue a entrada, não faça nada, exiba-a: o programa para gatos do WordMath.
Exemplo 2:
Think of a number, divide by 5, subtract from 9.
Lembre-se de que "dividir" é divisão de piso, portanto, para este programa 6 -> 8
, e 29 -> 4
.
Exemplo 3:
Think of a number, add 5, add 10, multiply by 2, subtract 15, repeat, divide by 2.
O programa estendido para gatos!
Exemplo 4:
Think of a number, subtract 1, repeat, repeat.
Pega um número e subtrai 3.
-5/3
? Nós arredondamos para0
ou em direção ao infinito negativo?Respostas:
05AB1E ,
59565452 bytesExperimente online!
Meu cérebro dói muito depois disso ... Ele gera no código 05AB1E da seguinte maneira:
Think of a Number
é removido devido a entrada implícita.Subtract From #
abrigos para#s-
(swapa
eb
e executar a operação).Subtract #
converte para#-
.Add #
converte para#+
.Multiply by #
converte para#*
.Divide by #
converte para#/
.Repeat
pega o que foi armazenado pela última vez no registro e o concatena.Explicado:
Exemplo:
Entrada:
Saída:
Experimente a solução com entrada 10:
Experimente online!
Veja no google:
Aqui está um link para a mesma equação digitada no google.
fonte
Pré-processador C, 362 bytes
Eu quase consegui isso trabalhando apenas no pré-processador C, mas o comando repeat acaba sendo muito difícil de implementar. Então, em vez disso, usei o pré-processador para transformar a entrada em uma matriz que é interpretada por algum código adicional.
A entrada deve ser fornecida em "input.wm" ou apenas despejada na fonte nessa linha. Incluí os bytes na minha contagem porque acho que é um pouco hacky e um pouco contra as regras do desafio, por isso é apenas adequado.
De qualquer forma, depois de despejar sua fonte do WordMath em input.wm, onde um compilador pode encontrá-lo, você poderá compilar isso, como está, com avisos para produzir um executável que faça o que a fonte do WordMath diz.
fonte
Retina, 170 bytes
Porque quem não gostaria de ver isso ?!
Pensei em como seria incrível ver uma solução Retina e decidi criá-la rapidamente. Levou apenas uma hora. Como sempre, a contagem de bytes assume a codificação ISO 8859-1.
Experimente online
A saída possui uma nova linha à direita que não deve ser copiada ao testar o programa resultante. O programa não suporta negativos, porque o intervalo inteiro padrão da Retina (em unário) não.
Explicação:
Programas de matemática:
Adicionar:
Adicione o número de unidades ao início. Adicione 5:
Subtrair:
Remova o número de unidades desde o início. Subtraia 5:
Subtrair de:
Substitua a entrada
1
s porx
s. Coloque ao lado do número fixo. Remova repetidamentex1
. Subtraia de 10:Multiplique por:
Substitua todos
1
por um certo número deles. Multiplique por 3:Dividido por:
Isso usa meu programa Retina para a Divisão Inteira . Divida por 2:
fonte
$
combina no final da sequência ou na frente de um avanço de linha à direita. Você precisa\z
se você quer apenas o primeiro.GNU awk, 139 bytes
Invocação:
Casos de teste:
fonte
Haskell,
232231 bytesObviamente, um programador funcional prefere retornar uma função ao invés de uma string que representa um programa, mas aqui vamos nós:
Comentários: Sempre começamos adicionando zero, caso contrário, a transpilação do programa trivial do WordMath não forneceria informações suficientes para inferir o tipo em que
read
é usado.subtract from n
poderia ser implementado como(n-)
, mas eu uso((-)n)
para mais uniformidade. No caso desubtract n
copiar osubtract
da entrada, não preciso escrevê-lo, mas preciso compensar o espaço que falta no final.repeat
é usado como operação padrão; juntamente com uma operação anterior inicial vazia, isso permite ignorar facilmente as quatro primeiras palavras.Exemplo de uso:
Os outros exemplos fornecem os seguintes resultados:
fonte
h
pode parecer algoh s n r|x<-s.read.init$n=x%r.x
e ser chamado no primeiro argumento de uma função comoh(+)n r
(e precisa haver algumflip
lugar para obter a ordem correta do operador), o caso base é_%_=id
. A função principal pode evitar todo o padrão e apenas sert l=id%words l
. - Graças ao currying, ele pode ser visto como um intérprete, e essa ideia pode levar a uma solução mais fácil e / ou mais curta.Python 2,
263258260221 bytesProvavelmente ainda poderia ser muito mais curto.
Experimente online
Eu uso em
//
vez de/
, porque a última instrução terá um.
no final, tornando qualquer número um float. Portanto, para manter a divisão consistente, eu uso a divisão inteira.Saída de casos de teste:
fonte
if
s parao
o seguinte (o que eu acho que deve funcionar):,o=[[o+[['+-'['s'in c],'//']['v'in c],'*']['m'in c]+n,n+'-'+o]['f'in c],'input()']['T'in c]
você pode baixá-lo para 224.Anterior,
342305 bytesExperimente online!
Saída
O código gerado começa com um
&
comando (valor de entrada) e termina com os comandos.
(valor de saída) e@
(saída). No meio, temos os vários cálculos no formulário<number><operation>
, onde a operação pode ser+
(somar),-
(subtrair),/
(dividir por),*
(multiplicar por) e\-
(subtrair de).O número em si é um pouco complicado, porque o Befunge suporta apenas literais numéricos no intervalo de 0 a 9, portanto, qualquer coisa maior que isso precisa ser calculada manualmente. Como já estamos lendo os números caractere a caractere, simplesmente aumentamos o número à medida que cada dígito é lido, por exemplo, 123 se torna
155+*2+55+*3+
, ie(((1 * 10) + 2) * 10) + 3
.Exemplos
Explicação
O Befunge não tem a capacidade de manipular seqüências de caracteres, portanto, a maior parte da análise é realizada pela contagem de caracteres. Começamos apenas pulando os 18 primeiros caracteres, o que nos leva a pensar em uma frase numérica (mais uma vírgula ou ponto). Então, se o próximo caractere for alguma forma de nova linha ou EOF, iremos diretamente para a rotina de saída, caso contrário, continuaremos procurando uma lista de comandos.
Para analisar um comando, continuamos contando caracteres até chegarmos a um dígito ou separador. Se é um separador, deve ter sido o comando de repetição que tratamos como um caso especial. Se for um dígito, o adicionamos ao nosso buffer de saída e continuamos procurando mais dígitos. Cada vez que um dígito é emitido, o prefixamos com
55+*
(para multiplicar o total até agora por 10) e o sufixamos com+
(para adicioná-lo ao total). Quando os dígitos terminam, adicionamos o caractere de comando.Quanto à forma como o comando é determinado, levamos a contagem de caracteres até o primeiro dígito do módulo 7. Para adicionar este é 4 (incluindo o espaço a seguir), para subtrair é 2, para dividir por 3, para multiplicar por 5 , e para subtrair dele é 0. O subtrair de requer um pouco de manipulação adicional, pois precisa da
\-
combinação de comandos, mas os outros apenas usam seu valor para procurar o caractere de comando apropriado em uma tabela.Esse processo é repetido para cada comando, construindo a saída em uma sequência pré-construída na linha 8. Cada vez que um comando adicional é adicionado, também adicionamos uma citação final à sequência para garantir que ela seja sempre finalizada corretamente. Então, quando finalmente chegamos ao final de nossa entrada, simplesmente "executamos" essa string para empurrá-la para a pilha e, em seguida, seguimos com uma sequência de saída padrão para escrever tudo.
fonte
JavaScript (ES6), 163 bytes
Tente:
fonte
Vim
208171168 bytesFoi adicionada a capacidade de fazer várias repetições consecutivas, como @ Flp.Tkc, mas gerando bytes suficientes para que eu ainda pudesse diminuir a contagem de bytes.
TryItOnline
Caracteres não imprimíveis:
Saída de casos de teste:
cw^R=^R" ^[
TryItOnlinecw^R=((^R" /5) *-1+9) ^[
TryItOnlinecw^R=((((((^R" +5) +10) *2) -15) -15) /2) ^[
TryItOnlinefonte
lex, 246 bytes
lex tem como alvo C, portanto, um compilador C precisaria compilá-lo em algo executável. A biblioteca lexer (
ll
) também precisaria estar vinculada. Isso pode adicionar uma penalidade de bytes, mas não tenho certeza de quantos bytes, se houver.O programa gera um programa lex (por especificação) que avalia a expressão de texto transpilado. O código entre
%{
e%}
é apenas para o "transpiler":Entre as duas
%%
linhas está a parte regex / action. A primeira regra a ser correspondida seriaT
("Think ...") que constrói o preâmbulo (os programas lex devem iniciar pelo menos a seção de regras e oyytext
último texto correspondente, portanto, a regra basicamente semeia o acumulador com a entrada do usuário )As devoluções do programa todas as entradas, exceto para o que for compatível, e as outras regras (
ad
,fr
atére
) lidar com as cláusulas de expressão wordmath com como jogo um mínimo possível de ser único. Na maioria deles, ele definec
um infixo de expressão, que é concatenado entren
e o último número inteiro lido quandoO
é chamado (por exemplo, a leitura de "add 9" definirá o infixo como+=
, v para9
, e a chamadaO
será exibidan+=9;
) . (Um aspecto interessante é que "subtrair de 8" fará com ques
asfr
regras e as regras sejam correspondidas, mas comoO
é chamado apenas no número, a regra apropriadan=-n+8;
é a única expressão que obtém saída). Are
regra para "repetir" apenas chamaO
novamente, que gera a última expressão criada (e, como as correspondências subseqüentes serão derrotadasyytext
, o suporte à "repetição" é o motivo pelo qual a conversão de número inteiro na[0-9]+
regra foi necessária). Finalmente, um período faz com que o trailer do programa seja produzido, o que apenas gera o acumulador e fecha com o%%
par que indica o final do programa de saída lex.Nota: Nem o programa principal do transpilador nem o programa de saída serão finalizados. A entrada da tubulação funcionaria ou fornecer EOF (ctrl-D). Se a finalização for necessária após a primeira entrada, é possível adicionar exit () s.
Para criar / executar:
Teste 1:
Teste 2:
Teste 3:
Teste 4:
fonte
Pitão,
6967 bytesUm programa que recebe a entrada de
"quoted string"
e imprime o resultado.Suíte de teste
Como funciona
Pyth possui operadores de prefixo, portanto, as operações aritméticas básicas são executadas usando
(operator)(operand1)(operand2)
, enquanto a variável pré-inicializadaQ
fornece a entrada. Portanto, um programa WordMath transpilado é construído iniciando com a sequência'Q'
e, em cada estágio, precedido pelo operador e, em seguida, precedido ou anexado ao operando como necessário.J\Q
DefinaJ
, a sequência de programas transpilada, como a sequência'Q'
tcQ\,
Divida a entrada por vírgulas e descarte o primeiro elemento (que é 'Think of a number'
)V
PoisN
nisso:Iq@N1\r
Se o caractere emN[1]
for'r'
(repita):=NZ
DefinidoN
comoZ
(valor anterior deN
, definido no final do loop for)x"asdm"@N1
Encontre o índice deN[1]
in"asdm"
(adicione, subtraia, divida, multiplique)@"+-/*"
Índice com isso em"+-/*"
, fornecendo o operador necessário,J-eCN)\.
Rendimento da lista de dois elementos[J, -eCN)\.]
, em que o segundo elemento é o último elemento daN
divisão no espaço em branco com qualquer'.'
caractere removido (operando)qh@cN)1\f
Se o primeiro caractere do segundo elemento daN
divisão no espaço em branco for'f'
(subtrair de):.>
Troque os elementos da lista de dois elementos+
Mesclar o operador e a lista de dois elementos em uma lista=Jjd
DefinidoJ
como aquele unido em espaços=ZN
DefinaZ
comoN
J
ImpressãoJ
fonte
Pip , 58 bytes
Pena que ainda não implementei esse operador de subtração reversa.
O programa pega um script do WordMath de stdin e gera o código Pip para stdout. O código que é produzido, da mesma forma, pega um número de stdin e gera o resultado em stdout. Experimente online!
Estratégia
Para entrada como esta:
queremos uma saída como esta:
que funciona da seguinte maneira:
Ungolfed + explicação
A estrutura básica do programa é
{...}Mq^k
, que divideq
(uma linha de stdin) emk
(vírgula-espaço) eM
aps uma função para cada elemento.Dentro da função, começamos tratando o
repeat
caso. O teste mais curto no Pip parece sersNa
(existe um espaço no comando). Se sim, queremos usara
; caso contrário, usep
, que armazena o comando anterior. Atribua esse valor de volta paraa
e também parap
(da próxima vez).Para nosso valor de retorno, usamos uma lista, o que é bom porque o formato de saída padrão para listas é concatenar tudo juntos. O resultado sempre começa com
Y
. Em seguida, precisamos de uma tabela de pesquisa para as operações.Observe que os comprimentos de
add
(4),subtract
(9),divide by
(10),multiply by
(12) esubtract from
(14) são todos distintos. Além disso, observe que eles ainda são distintos quando usados no mod 7. Assim, podemos usá-los para indexar em uma lista de sete elementos (contendo cinco trechos de código e dois espaços reservados) para mapear cada comando do WordMath para o código Pip apropriado (projetado para o número pode simplesmente ser concatenado até o final):-y+
(subtract from
)y-
(subtract
)y//
(divide by
)y+
(add
)y*
(multiply by
)Para os índices, usamos regex para obter o índice do primeiro dígito no comando:
a@?`\d`
. Também puxamos a regexy
para uso futuro. A tabela de pesquisa é gerada dividindo a sequência"-y+ y- y// y+ y* "
ems
(espaço).Ainda precisamos lidar com a primeira entrada, que deve ser traduzida no código
Yq
. ComoThink of a number
não contém dígitos, o@?
operador retorna nulo. Usar nil como um índice na tabela de pesquisa também retorna nil. Nada é falso, então tudo o que precisamos fazer é adicionar|'q
ao uso emq
vez de uma operação para este caso.O elemento final da lista retornada é o próprio número. Obtemos isso via
a@y
(encontre todas as correspondências no comando do regex de dígitos que arrancamos anteriormente). Isso retorna uma lista de dígitos, mas, novamente, não é um problema, porque todas as listas serão concatenadas na saída. Para a primeira entrada,a@y
não corresponde a nenhum dígito e fornece uma lista vazia, o que não adiciona nada à saída.Por exemplo
Com entrada
a expressão do mapa fornece a lista
que, quando concatenado, gera
fonte
Python 2 ,
154153146 bytesCorrigido e até salvo vários bytes no processo. ^ __ ^
Experimente online!
Com base na mesma estratégia da minha resposta Pip . Recursos específicos do Python:
Think of
e o fechamento.
é removido da string antes de dividir (input()[9:-1]
). O período foi muito incômodo para lidar com o loop principal. A remoção dos nove primeiros caracteres ajuda por um motivo diferente (veja abaixo).import re
), usamosrfind(" ")
para encontrar o último espaço no comando. Também podemos usar isso para verificar orepeat
caso.a number
que o índice do espaço está1
. Esse índice preenche convenientemente o outro orifício na tabela de pesquisa. O outro problema com o processamento do estágio de entrada no loop principal era a+c[s:]
parte que resultaria emx=input() number
. Para resolver esse problema, multiplicamos por stringc[0]<"a"
:1
para todos os comandos regulares, nos quaisc
começa com um espaço, mas0
para o iniciala number
.fonte
WinDbg,
449388 bytes-61 bytes, definindo alias para código repetido
Inspirado pelo uso de LambdaBeta
#define
. Essa abordagem modifica ligeiramente a sintaxe do WordMath (,
e.
deve ser delimitada por espaço como as outras palavras, e,
não seguerepeat
) e cria um alias para que a sintaxe do WordMath modificada seja um código WinDbg válido. A última linha faz o que a pergunta pede e transpila, convertendo a entrada na sintaxe modificada.A entrada é obtida definindo uma sequência em um endereço de memória e configurando o pseudo-registro
$t0
para esse endereço. Nota: isso substituirá oint
at0x2000000
, portanto, se você iniciar sua string lá, ela será parcialmente substituída.$t0
também será substituído.Como ele cria aliases, dependendo se esse código foi executado antes ou depois de definir a sequência, o código de saída será diferente (alias ou não). Infelizmente, não encontrei uma maneira de fazer com que os aliases se expandissem corretamente sem serem delimitados por espaços em branco (o que significa que o script do WordMath não poderia ser executado diretamente diretamente sem ser transformado primeiro).
Como funciona:
Exemplo de saída, inserindo a string antes de executar este código uma vez (o programa resultante se assemelha ao WordMath):
Exemplo de saída, inserindo a sequência após a execução desse código uma vez (os aliases são expandidos ao inserir a sequência, para que o programa resultante não seja tão bonito):
Um pouco mais de exemplo de saída, apenas usando a sintaxe do WordMath ligeiramente modificada:
fonte
Scala, 338 bytes
Experimente você mesmo em ideone
Explicação:
fonte