Zaimplementuj kalkulator graficzny

12

Było wiele pytań dotyczących kalkulatorów; jednak nie wydaje się, aby jakiekolwiek obejmowały wdrożenie kalkulatora graficznego.

Wyzwanie

Masz napisać kompletny program, który pobiera wiele formuł jako dane wejściowe z STDIN i zapisuje je w STDOUT. Dane wejściowe przyjmą formę f1(x)=x^2-x-1. Pojawią fsię cyfry 0–9 (włącznie), a (x)=następnie formuła do wykresu. Twój program powinien być w stanie pobierać dane wejściowe, wykresy, dane wejściowe, wykresy itp.

To jest kod golfowy.

Twój wykres powinien mieć zakres osi X od -5 do 5, z rozdzielczością co najmniej jednego punktu co 1/2 jednostki. Wymagania względem osi Y są takie same. Może się to wydawać małym zasięgiem w porównaniu do współczesnych kalkulatorów, ale najprawdopodobniej zwiększenie tego będzie trywialne. Na wykresie powinna być narysowana oś z zaznaczonymi znacznikami w postaci +liczb całkowitych.

Formułę należy oceniać w normalnej kolejności działania. W tych formułach nie będzie żadnych pionowych asymptot / niezdefiniowanych regionów. Zmienna zawsze będzie miała wartość x. Jeśli dwie formuły zostaną wprowadzone z tym samym numerem równania, najstarszy należy usunąć i zastąpić nową formułą. Puste formuły powinny być wyzerowane. Ponieważ jest prawdopodobne, że formuła nie zawsze da ładną wielokrotność 1/2, należy zaokrąglić do najbliższej 1/2.

Kiedy formuła jest wykreślana, jej linia powinna być utworzona z liczby formuły. Gdy linia przecina oś, oś należy narysować na górze. Kiedy dwie linie przecinają się, nie ma znaczenia, który jest pokazany.

Przykładowe dane wejściowe

f1(x)=x+1

Wynik

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

Wejście

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

Wynik

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

Wejście

f1(x)=-x  

(uwaga, program może odrzucić to wejście i tylko z wyjątkiem 0-x lub x * -1, ale należy to udokumentować)

Wynik

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
źródło

Odpowiedzi:

5

Perl, 177 znaków (przełącznik wiersza poleceń +1)

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}'

Według tego meta wątku uważam, że powinno to łącznie liczyć 178 znaków.

Podobnie jak w przypadku rozwiązania Ruby, Używam również evali wymiana ^z **.

Analiza wejściowa jest jednocześnie niewiarygodnie delikatna i niezwykle odporna: f1(x)=może być napisana jako, f 1 ( x ) =a foo 1 bar =nawet po prostu 1=, ale bardzo dziwne rzeczy mogą się zdarzyć, jeśli fzastąpisz ją czymś, co nie jest prawidłową, bezskuteczną instrukcją Perla. Zostałeś ostrzeżony.

Inne szczegóły to także sposób oś pionowa jest narysowany, który wykorzystuje fakt, że XOR bitowe znaki +i |jest W. Oczywiście nie będzie to działać w systemach EBCDIC.

Dane wyjściowe są renderowane jako skrót tablic, a nie tablica tablic - okazuje się, że potrzeba mniejszej liczby znaków, aby jawnie obciąć klucze skrótu do liczb całkowitych, a następnie zapętlić wycinek skrótu, aby upewnić się, że tablica nie jest indeksowane wartościami ujemnymi. Mógłbym ogolić jeszcze dwa znaki, gdyby nie irytujący sposób, w jaki Perl intskraca wartości ujemne do zera, co zmusiło mnie do numeracji rzędów wyjściowych od 2 do 22 zamiast od 0 do 20, aby uniknąć zaokrąglania artefaktów na górnej krawędzi obszaru wyjściowego.

Korzystam z liberalnej konwersji Perla na ciąg znaków w parsowaniu danych wejściowych, gdzie używam całego łańcucha 1(x)=jako indeksu tablicy (jest konwertowany na tylko 1).

Mógłbym również zapisać trzy kolejne znaki (i uczynić parsowanie nieco bardziej niezawodnym), zastępując s/\d.*=/;/;$f[$&]=$_je /\d.*=/;$f[$&]=$', ale wtedy musiałbym wydać taką samą liczbę dodatkowych znaków na napisanie, $'jak $'\''w łańcuchu pojedynczego cudzysłowu. Przypuszczam, że technicznie nie musiałbym ich liczyć, ale wydaje mi się, że to oszustwo.

Ilmari Karonen
źródło
6

Ruby, 200 znaków

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

Zwykła implementacja ruby ​​przy użyciu standardowego ewaluatora dla wyrażeń ( ^zostanie zastąpiona, aby powyższe przykłady działały poprawnie). Nie jest bardzo solidny i zakłada dane wejściowe dokładnie tak, jak określono w pytaniu.

Howard
źródło
Czy w piątej linii mógłbyś zmienić y*0.5się y/2i pozbyć dwóch postaci? Nie znam Ruby, więc może nie mam racji.
PhiNotPi
2
@PhiNotPi Niestety to nie zadziała. y/2dokonuje podziału na liczby całkowite.
Howard
Czy możesz użyć loop{}zamiast ()while 1?
defhlt
Znaleziono to poprzez link na pasku bocznym po prawej stronie. To całkiem dobrze zrobione. Miałem trochę zabawy, próbując zmniejszyć to, ale znalazłem tylko 9 bajtów , jeden bajt opierał się na racjonalnych literałach wprowadzonych w Ruby 2.1 (?).
blutorange
5

Python 2: 320 znaków

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)

Prawdopodobnie może być krótszy, ale jestem trochę nowicjuszem :)

Tworzenie Nzmiennej marnuje 9 znaków, ale podoba mi się to bardziej.

NicolasP
źródło