Implementieren Sie einen Grafikrechner

12

Es gab viele Fragen, die Taschenrechner betrafen; Es scheint jedoch nicht so, als würde ein Grafikrechner implementiert.

Die Herausforderung

Sie müssen ein vollständiges Programm schreiben, das mehrere Formeln als Eingabe von STDIN verwendet und diese in STDOUT grafisch darstellt. Die Eingabe erfolgt in der Form f1(x)=x^2-x-1. Es wird ein fgefolgt von einer Nummer 0-9 (einschließlich), gefolgt von(x)= , gefolgt von der Formel, die grafisch dargestellt werden soll. Ihr Programm sollte in der Lage sein, Eingaben, Grafiken, mehr Eingaben, Grafiken usw. zu erfassen.

Das ist Code Golf.

Ihr Diagramm sollte einen X-Achsenbereich von -5 bis 5 mit einer Auflösung von mindestens einem Punkt pro 1/2 Einheit haben. Die Anforderungen an die Y-Achse sind gleich. Dies mag im Vergleich zu modernen Rechnern wie ein kleiner Bereich erscheinen, aber es wird höchstwahrscheinlich trivial sein, dies zu erhöhen. Auf dem Diagramm sollte die Achse mit Häkchen in Form von gezeichnet sein+ Ganzzahlen .

Die Formel sollte in der normalen Betriebsreihenfolge ausgewertet werden. In diesen Formeln gibt es keine vertikalen Asymptoten / undefinierten Regionen. Die Variable wird immer x sein. Wenn zwei Formeln mit derselben Gleichungsnummer eingegeben werden, sollte die älteste gelöscht und durch die neue Formel ersetzt werden. Leere Formeln sollten mit Null bewertet werden. Da es wahrscheinlich ist, dass die Formel nicht immer ein nettes Vielfaches von 1/2 ergibt, müssen Sie auf die nächste 1/2 runden.

Wenn eine Formel grafisch dargestellt wird, sollte ihre Linie aus der Nummer der Formel gebildet werden. Wenn eine Linie eine Achse kreuzt, sollte die Achse oben gezeichnet werden. Wenn sich zwei Linien kreuzen, spielt es keine Rolle, welche angezeigt wird.

Beispiel Eingabe

f1(x)=x+1

Ausgabe

          +       1
          |      1
          +     1
          |    1
          +   1
          |  1
          + 1
          |1
          +
         1|
+-+-+-+-+-+-+-+-+-+-+
       1  |
      1   +
     1    |
    1     +
   1      |
  1       +
 1        |
1         +
          |
          +

Eingang

f2(x)=(x^2)^0.25

Ausgabe

          +       1
          |      1
          +     1
          |    1
          +   1
          |  1
2222      + 1    2222
    222   |1  222
       22 + 22
         2|2
+-+-+-+-+-+-+-+-+-+-+
       1  |
      1   +
     1    |
    1     +
   1      |
  1       +
 1        |
1         +
          |
          +

Eingang

f1(x)=-x  

(Beachten Sie, dass Ihr Programm diese Eingabe nur mit Ausnahme von 0-x oder x * -1 ablehnen kann. Dies sollte jedoch dokumentiert werden.)

Ausgabe

1         +
 1        |
  1       +
   1      |
    1     +
     1    |
2222  1   +      2222
    2221  |   222
       22 + 22
         2|2
+-+-+-+-+-+-+-+-+-+-+
          |1
          + 1
          |  1
          +   1
          |    1
          +     1
          |      1
          +       1
          |        1
          +         1
PhiNotPi
quelle

Antworten:

5

Perl, 177 Zeichen (+1 Befehlszeilenschalter)

perl -nE 's!\^!**!g;s!x!(\$k/2-6)!g;s/\d.*=/;/;$f[$&]=$_;my%a;for$k(@x=2..22){$i=0;$a{int 12.5-2*eval}[$k-2]=$i++for@f}$p="|";$$_[10]=$p^=W,$a{12}=[$p."-+"x10],say map$_//$",@$_ for@a{@x}'

Per diesem Meta-Thread sollte dies insgesamt 178 Zeichen umfassen.

Wie die Ruby-Lösung verwende auch ich evalund ersetze ^durch** .

Der Eingang Parsing ist sowohl unglaublich zerbrechlich und unglaublich robust zugleich: f1(x)=kann geschrieben werden f 1 ( x ) =oder foo 1 bar =oder auch nur 1=, aber sehr seltsame Dinge passieren könnten , wenn man die ersetztf durch etwas keine gültige, nebenwirkungsfreie Perl-Anweisung ist. Du wurdest gewarnt.

Weitere Details von Interesse sind die Art und Weise, wie die vertikale Achse gezeichnet wird, wobei die Tatsache ausgenutzt wird, dass das bitweise XOR der Zeichen +und |istW . Offensichtlich funktioniert dies nicht auf EBCDIC-Systemen.

Die Ausgabe wird in einen Hash von Arrays und nicht in ein Array von Arrays gerendert. Es hat sich herausgestellt, dass weniger Zeichen erforderlich sind, um die Hash-Schlüssel explizit auf Ganzzahlen zu kürzen und dann eine Schleife über ein Hash-Slice zu erstellen, als erforderlich ist, um sicherzustellen, dass kein Array vorhanden ist mit negativen Werten indiziert. Ich könnte zwei weitere Zeichen abschneiden, wenn Perls intnegative Werte nicht auf ärgerliche Weise gegen Null abgeschnitten würden, was mich zwang, die Ausgabezeilen von 2 bis 22 statt von 0 bis 20 zu nummerieren, um Rundungsartefakte am oberen Rand zu vermeiden des Ausgabebereichs.

Ich verwende die liberale Konvertierung von Zeichenfolgen in Zahlen in der Eingabe-Analyse von Perl, wobei ich die gesamte Zeichenfolge 1(x)=als Array-Index verwende (sie wird in nur 1 konvertiert).

Ich könnte auch sparen drei weitere Zeichen (und macht die Analyse etwas robuste) durch den Austausch s/\d.*=/;/;$f[$&]=$_mit /\d.*=/;$f[$&]=$', aber dann würde ich die gleiche Anzahl von zusätzlichen Zeichen zu schreiben ausgeben muß $'als $'\''in einem einfachen Anführungszeichen Shell - String. Ich nehme an, technisch müsste ich diese nicht zählen, aber es fühlt sich irgendwie nach Schummeln an.

Ilmari Karonen
quelle
6

Ruby, 200 Zeichen

f={}
r=0..20
(f[gets[1]]=$_[6..-1].gsub /\^/,'**'
s=r.map{' '*21}
f.map{|n,k|r.map{|y|x=y*0.5-5
v=(2*eval(k)).round
v.abs<11&&y!=10&&s[10-v][y]=n
s[y][10]='+|'[y%2]
s[10][y]='+-'[y%2]}}
puts s)while 1

Eine einfache Ruby-Implementierung mit dem Standardauswertungsprogramm für Ausdrücke ( ^wird ersetzt, damit die oben angegebenen Beispiele gut funktionieren). Es ist nicht sehr robust und übernimmt die Eingabe genau wie in der Frage angegeben.

Howard
quelle
Auf der fünften Zeile ändern, könnten Sie y*0.5zu y/2und werde zwei Charaktere loswerden? Ich kenne Ruby nicht, also kann ich nicht richtig liegen.
PhiNotPi
2
@PhiNotPi Leider funktioniert das nicht. y/2tut ganzzahlige Division.
Howard
Können Sie loop{}anstelle von verwenden ()while 1?
Defhlt
Finden Sie dies über den Link auf der Seitenleiste auf der rechten Seite. Das ist ziemlich gut gemacht. Ich hatte ein bisschen Spaß beim Versuch, diese zu verkleinern, fand aber nur 9 Bytes , wobei sich ein Byte auf die in Ruby 2.1 (?) Eingeführten rationalen Literale stützte.
blutorange
5

Python 2: 320 Zeichen

N=20
r=range(N+1)
d={}
while(1):
 l=raw_input()
 d[l[1]]=l[6:].replace('^','**')
 g=[[' ']*(N+1) for i in r]
 for n,f in d.items():
  for x in r:
   v=N/2+int(round(2*eval(f.replace('x','(%f)'%(x/2.0-N/4)))))
   if 0<=v<=N:g[N-v][x]=n
 for i in r:
  g[i][N/2]='+|'[i%2]
  g[N/2][i]='+-'[i%2]
 for l in g:print''.join(l)

Könnte wahrscheinlich kürzer gemacht werden, aber ich bin ein bisschen ein Neuling in diesem :)

Wenn man Neine Variable erstellt, werden 9 Zeichen verschwendet, aber so gefällt es mir besser.

NicolasP
quelle