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.

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.


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

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]"

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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.