Gere um programa de golfe para avaliar uma expressão aritmética

8

Sua tarefa é escrever um programa que receba entradas como esta:

a + b * c + a / 2

e gerará o código-fonte para um programa que recebe a entrada do usuário e avalia a expressão.

A expressão pode conter os operadores +, -, *, /; variáveis ​​minúsculas de uma letra; e números inteiros entre 0 e 32000. A precedência aritmética padrão deve ser seguida corretamente. A expressão é limitada a 26 variáveis ​​únicas de a a z. No entanto, uma única variável pode aparecer mais de uma vez.

Você pode assumir que a expressão de entrada é válida (segue estas regras).

O programa gerado deve solicitar a entrada do usuário neste formulário, solicitando apenas uma vez para cada variável:

a = 

A entrada do usuário de 0 a 32000 deve ser tratada corretamente. Em seguida, imprimirá a expressão e o resultado correto. Você pode usar aritmética de número inteiro ou de ponto flutuante. Os cálculos devem ser realizados com pelo menos precisão de 32 bits. Além disso, você não precisa se preocupar com excesso ou divisão por zero.

Exemplo de um programa Perl gerado sem golfe para a expressão acima:

print "a = ";
my $a = <>;
print "b = ";
my $b = <>;
print "c = ";
my $c = <>;
print "a + b * c + a / 2 = " . ($a + $b * $c + $a / 2); 

Exemplo de entrada e saída do programa gerado para a expressão acima:

a = 1
b = 2
c = 3
a + b * c + a / 2 = 7.5

A pontuação é calculada como o comprimento do programa + o comprimento do programa gerado para esta expressão:

1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000

Menor pontuação ganha.

Atualização: Apenas para destacar alguns requisitos do problema, conforme declarado acima:

  • A saída do programa deve ser o código fonte de outro programa que avalie a expressão.
  • O programa deve imprimir a expressão original . Talvez haja alguma ambiguidade nisso (alguém poderia argumentar que a+bé a mesma expressão que a + b), mas, para maior clareza, digamos que deve ser a expressão original com o espaço em branco intacto. Todas as respostas válidas até agora o fizeram dessa maneira.

fonte

Respostas:

1

Perl, 80 + 110 = 190

Inspirado diretamente por outra resposta (agora excluída) em Ruby. Requer Perl ≥ v5.14.

Seguindo a regra usual que vi de opções de linha de comando contando como um caractere.

#!/usr/bin/perl -n
chomp;print'print $_="',$_,'"," = ",eval(s#\pL#${$&}//=do{print"$& = ";<>}#ger)'

Perl, 80 + 231 = 311

Porque avaliar a produção parece barato.

#!/usr/bin/perl -p
chomp;print"print '$_ = ',";s/\pL/$s{$&}++?"\$$&":"do{print'$& = ';\$$&=<>}"/ge

Parece que a saída pode ser reduzida, movendo o prompt para um sub, mas fiquei sem entusiasmo.

Kevin Reid
fonte
Isso é código de golfe. Avaliar a produção não é barato!
Algumas sugestões: \pLpode substituir [a-z]. Não há necessidade de dobloqueio. Pode simplesmente escrever:${$&}//=print"$& = "and<>
@ dan1111 Obrigado pelo \pLfeito. Não é possível usar andem nenhum dos programas, porque a precedência é muito baixa; andtem precedência menor que //=.
Kevin Reid
1

Lua, 202 + 166 = 368

Arquivo "generate_code.lua"

F=...
C='function G(v)io.write(v.." = ")_G[v]=io.read"*n"end 'V={}for v in F:gmatch'%l'do V[v]=0 end
for v in pairs(V)do C=C..'G"'..v..'"'end
print(C..'F="'..F..'"print(F.." = "..load("return "..F)())')

Uso:

$ lua generate_code.lua "1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000"

Código gerado (a ordem das variáveis ​​não está especificada):

function G(v)io.write(v.." = ")_G[v]=io.read"*n"end G"g"G"e"G"d"G"b"G"a"G"h"F="1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000"print(F.." = "..load("return "..F)())

Código gerado em ação:

g = 4
e = 3
d = 2
b = 1
a = 6.5
h = 4.3
1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000 = 29787.941860465
Egor Skriptunoff
fonte
1

Tcl 198 + 155 = 352

gets stdin i;puts [string map [list @ [lsort -u [regexp -all -inline {[a-z]} $i]] & [regsub -all {[a-z]} [join $i {}] {$\0}] | $i] {foreach va {@} {puts "$va =";gets stdin $va};puts "| = [expr &]"}]

gera

foreach va {a b d e g h} {puts "$va =";gets stdin $va};puts "1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000 = [expr 1+$a*4*$b+2/$d*$e-$a-3+$g/$h*32000]"
Johannes Kuhn
fonte
foreach=> lmap; va=>v
sergiol
0

Python 125 + 151 = 276

>>> t=raw_input();z=sorted(set(filter(str.isalpha,t)));print','.join(z)+'=[input(x+" = ")for x in%r];print"%s =",%s'%(z,t,t[::2])
1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000
a,b,d,e,g,h=[input(x+" = ")for x in['a', 'b', 'd', 'e', 'g', 'h']];print"1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000 =",1+a*4*b+2/d*e-a-3+g/h*300

Agora executando:

>>> exec"""a,b,d,e,g,h=[input(x+" = ")for x in['a', 'b', 'd', 'e', 'g', 'h']];print"1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000 =",1+a*4*b+2/d*e-a-3+g/h*300"""
a = 1
b = 2
d = 3
e = 4
g = 5
h = 6
1 + a * 4 * b + 2 / d * e - a - 3 + g / h * 32000 = 5
jamylak
fonte
Eu não acho que exista nenhum requisito para classificar as variáveis ​​e acho que é melhor usar uma string literal em vez de uma lista. Ou seja, substitua z=sorted(set(filter(str,isalpha,t)))por z=''.join(set(filter(str.isalpha,t))).
precisa saber é o seguinte