Generar un programa de golf para evaluar una expresión aritmética.

8

Su tarea es escribir un programa que tome datos como este:

a + b * c + a / 2

y generará el código fuente para un programa que toma la entrada del usuario y luego evalúa la expresión.

La expresión puede contener los operadores +, -, *, /; variables minúsculas de una letra; y enteros entre 0 y 32000. La precedencia aritmética estándar debe seguirse correctamente. La expresión está limitada a 26 variables únicas de la a a la z. Sin embargo, una sola variable puede aparecer más de una vez.

Puede suponer que la expresión de entrada es válida (sigue estas reglas).

El programa generado debe solicitar la entrada del usuario en este formulario, solicitando solo una vez para cada variable:

a = 

La entrada del usuario de 0 a 32000 debe manejarse correctamente. Luego imprimirá la expresión y el resultado correcto. Puede usar aritmética de enteros o de coma flotante. Los cálculos deben realizarse con al menos 32 bits de precisión. Más allá de eso, no tiene que preocuparse por el desbordamiento o dividir por cero.

Ejemplo de un programa Perl generado sin golf para la expresión anterior:

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

Ejemplo de entrada y salida del programa generado para la expresión anterior:

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

La puntuación se calcula como la longitud del programa + longitud del programa generado para esta expresión:

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

La puntuación más baja gana.

Actualización: Solo para resaltar un par de requisitos del problema, como se indicó anteriormente:

  • La salida del programa debe ser el código fuente de otro programa que evalúe la expresión.
  • El programa debe imprimir la expresión original . Quizás haya cierta ambigüedad en esto (se podría argumentar que a+bes la misma expresión que a + b), pero para mayor claridad, digamos que debe ser la expresión original con el espacio en blanco intacto. Todas las respuestas válidas hasta ahora lo han hecho de esa manera.

fuente

Respuestas:

1

Perl, 80 + 110 = 190

Directamente inspirado por otra respuesta (ahora eliminada) en Ruby. Requiere Perl ≥ v5.14.

Siguiendo la regla habitual que he visto de los interruptores de línea de comandos que cuentan como un carácter.

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

Perl, 80 + 231 = 311

Porque evaluar en la salida se siente barato.

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

Parece que la salida podría acortarse moviendo la solicitud a un sub, pero me he quedado sin entusiasmo.

Kevin Reid
fuente
Este es el código de golf. ¡Evaluar la salida no es barato!
Algunas sugerencias: \pLpuede reemplazar [a-z]. No hay necesidad de dobloquear. Puede escribir:${$&}//=print"$& = "and<>
@ dan1111 Gracias por el \pLhecho. No se puede usar anden ninguno de los programas, porque la precedencia es demasiado baja; andtiene menor precedencia que //=.
Kevin Reid
1

Lua, 202 + 166 = 368

Archivo "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 generado (no se especifica el orden de las variables):

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 generado en acción:

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
fuente
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 &]"}]

genera

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
fuente
foreach=> lmap; va=>v
sergiol
0

Pitón 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

Ahora ejecutándolo:

>>> 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
fuente
No creo que haya ningún requisito para ordenar las variables y creo que es mejor usar un literal de cadena en lugar de una lista. Es decir, reemplazar z=sorted(set(filter(str,isalpha,t)))con z=''.join(set(filter(str.isalpha,t))).
Geoff Reedy