Generieren Sie ein Golfprogramm, um einen arithmetischen Ausdruck auszuwerten

8

Ihre Aufgabe ist es, ein Programm zu schreiben, das folgende Eingaben übernimmt:

a + b * c + a / 2

und generiert den Quellcode für ein Programm , das Benutzereingaben entgegennimmt und dann den Ausdruck auswertet.

Der Ausdruck kann die Operatoren enthalten +, -, *, /; Kleinbuchstaben in Kleinbuchstaben; und ganze Zahlen zwischen 0 und 32000. Die standardmäßige arithmetische Priorität muss korrekt befolgt werden. Der Ausdruck ist auf 26 eindeutige Variablen a bis z beschränkt. Eine einzelne Variable kann jedoch mehrmals vorkommen.

Sie können davon ausgehen, dass der Eingabeausdruck gültig ist (folgt diesen Regeln).

Das generierte Programm muss zur Benutzereingabe in diesem Formular auffordern und für jede Variable nur einmal zur Eingabe auffordern:

a = 

Benutzereingaben von 0 bis 32000 sollten korrekt behandelt werden. Es wird dann der Ausdruck und das richtige Ergebnis gedruckt. Sie können entweder eine Ganzzahl- oder eine Gleitkomma-Arithmetik verwenden. Die Berechnungen sollten mit einer Genauigkeit von mindestens 32 Bit durchgeführt werden. Darüber hinaus müssen Sie sich keine Gedanken über Überlauf machen oder durch Null teilen.

Beispiel eines nicht Golf-generierten Perl-Programms für den obigen Ausdruck:

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

Beispiel für die Eingabe und Ausgabe eines Programms, das für den obigen Ausdruck generiert wurde:

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

Die Punktzahl wird berechnet als Länge des Programms + Länge des generierten Programms für diesen Ausdruck:

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

Die niedrigste Punktzahl gewinnt.

Update: Nur um einige Anforderungen des Problems hervorzuheben, wie oben angegeben:

  • Die Ausgabe des Programms muss Quellcode für ein anderes Programm sein , das den Ausdruck auswertet.
  • Das Programm muss den ursprünglichen Ausdruck drucken . Vielleicht gibt es eine gewisse Mehrdeutigkeit (man könnte argumentieren, dass dies a+bder gleiche Ausdruck ist wie a + b), aber der Klarheit halber nehmen wir an, dass es der ursprüngliche Ausdruck mit intaktem Leerraum sein muss. Alle bisher gültigen Antworten haben es so gemacht.

quelle

Antworten:

1

Perl, 80 + 110 = 190

Direkt inspiriert von einer anderen (jetzt gelöschten) Antwort in Ruby. Benötigt Perl ≥ v5.14.

Nach der üblichen Regel habe ich Befehlszeilenschalter gesehen, die als ein Zeichen zählen.

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

Perl, 80 + 231 = 311

Weil sich eine Auswertung der Ausgabe billig anfühlt.

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

Es scheint, als könnte die Ausgabe verkürzt werden, indem die Eingabeaufforderung in ein Sub verschoben wird, aber mir ist die Begeisterung ausgegangen.

Kevin Reid
quelle
Das ist Code Golf. Die Auswertung der Ausgabe ist nicht billig!
Ein paar Vorschläge: \pLkönnen ersetzen [a-z]. Keine Notwendigkeit für doBlock. Kann nur schreiben:${$&}//=print"$& = "and<>
@ dan1111 Danke für das \pL, fertig. Kann andin keinem Programm verwendet werden, da die Priorität zu niedrig ist. andist niedriger Vorrang als //=.
Kevin Reid
1

Lua, 202 + 166 = 368

Datei "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)())')

Verwendungszweck:

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

Code generiert (Reihenfolge der Variablen nicht angegeben):

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)())

Generierter Code in Aktion:

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

erzeugt

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
quelle
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

Jetzt ausführen:

>>> 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
quelle
Ich glaube nicht, dass es notwendig ist, die Variablen zu sortieren, und ich denke, es ist besser, ein String-Literal anstelle einer Liste zu verwenden. Das heißt, ersetzen z=sorted(set(filter(str,isalpha,t)))durch z=''.join(set(filter(str.isalpha,t))).
Geoff Reedy