Mettre en œuvre une calculatrice graphique

12

Il y a eu de nombreuses questions concernant les calculatrices; cependant, il ne semble pas que cela implique la mise en œuvre d'une calculatrice graphique.

Le défi

Vous devez écrire un programme complet qui prend plusieurs formules en entrée de STDIN et les représente graphiquement dans STDOUT. La saisie prendra la forme f1(x)=x^2-x-1. Il y aura un fsuivi d'un nombre 0-9 (inclus), suivi de (x)=, suivi de la formule à représenter graphiquement. Votre programme devrait être capable de prendre des entrées, des graphiques, de prendre plus d'entrées, des graphiques, etc.

C'est le golf de code.

Votre graphique doit avoir la plage de l'axe X de -5 à 5, avec une résolution d'au moins un point toutes les 1/2 unités. Les exigences de l'axe Y sont les mêmes. Cela peut sembler une petite plage par rapport aux calculatrices modernes, mais il sera très probablement insignifiant d'augmenter cela. Le graphique doit avoir l'axe dessiné sur eux, avec des graduations sous la forme de +sur les entiers.

La formule doit être évaluée avec l'ordre normal de fonctionnement. Il n'y aura pas d'asymptotes verticales / régions indéfinies dans ces formules. La variable sera toujours x. Si deux formules sont entrées avec le même numéro d'équation, la plus ancienne doit être effacée et remplacée par la nouvelle formule. Les formules vides doivent être évaluées à zéro. Comme il est probable que la formule ne donne pas toujours un joli multiple de 1/2, vous devez arrondir au 1/2 le plus proche.

Lorsqu'une formule est représentée graphiquement, sa ligne doit être formée à partir du numéro de la formule. Lorsqu'une ligne croise un axe, l'axe doit être tracé en haut. Lorsque deux lignes se croisent, peu importe ce qui est affiché.

Exemple d'entrée

f1(x)=x+1

Production

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

Contribution

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

Production

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

Contribution

f1(x)=-x  

(Remarque, il est acceptable que votre programme rejette cette entrée et uniquement à l'exception de 0-x ou x * -1, mais cela doit être documenté)

Production

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
la source

Réponses:

5

Perl, 177 caractères (+1 commutateur de ligne de commande)

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

D'après ce fil méta , je pense que cela devrait compter 178 caractères au total.

Comme la solution Ruby, j'utilise evalet remplace également ^par **.

L'analyse en entrée est à la fois incroyablement fragile et incroyablement robuste: elle f1(x)=peut être écrite comme f 1 ( x ) =ou foo 1 bar =même juste 1=, mais des choses très étranges peuvent se produire si vous remplacez le fpar quelque chose qui n'est pas une instruction Perl valide et sans effet secondaire. Tu étais prévenu.

D'autres détails intéressants incluent la façon dont l'axe vertical est dessiné, qui exploite le fait que le XOR au niveau du bit des caractères +et |est W. De toute évidence, cela ne fonctionnera pas sur les systèmes EBCDIC.

La sortie est rendue dans un hachage de tableaux, pas un tableau de tableaux - il s'avère qu'il faut moins de caractères pour tronquer explicitement les clés de hachage en entiers, puis boucler sur une tranche de hachage qu'il ne faut pour s'assurer qu'un tableau n'est pas indexé avec des valeurs négatives. Je pourrais raser deux autres caractères si ce n'était pour la façon ennuyeuse dont Perl inttronque les valeurs négatives vers zéro, ce qui m'a forcé à numéroter les lignes de sortie de 2 à 22 au lieu de 0 à 20 afin d'éviter d'arrondir les artefacts au bord supérieur de la zone de sortie.

J'utilise la conversion libérale de chaîne en nombre de Perl dans l'analyse syntaxique d'entrée, où j'utilise la chaîne entière 1(x)=comme index de tableau (elle est convertie en seulement 1).

Je pourrais également enregistrer trois caractères supplémentaires (et rendre l'analyse légèrement plus robuste) en les remplaçant s/\d.*=/;/;$f[$&]=$_par /\d.*=/;$f[$&]=$', mais je devrais alors dépenser le même nombre de caractères supplémentaires pour écrire $'que $'\''dans une chaîne de shell entre guillemets simples. Je suppose que techniquement, je n'aurais pas à les compter, mais ça ressemble un peu à de la triche.

Ilmari Karonen
la source
6

Ruby, 200 caractères

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

Une implémentation ruby ​​simple utilisant l'évaluateur standard pour les expressions ( ^sera remplacée afin que les exemples donnés ci-dessus fonctionnent correctement). Il n'est pas très robuste et suppose l'entrée exactement comme spécifié dans la question.

Howard
la source
Sur la cinquième ligne, pourriez - vous changer y*0.5à y/2et de se débarrasser de deux personnages? Je ne connais pas Ruby, donc je n'ai peut-être pas raison.
PhiNotPi
2
@PhiNotPi Malheureusement, cela ne fonctionnera pas. y/2fait une division entière.
Howard
Pouvez-vous utiliser à la loop{}place de ()while 1?
defhlt
Trouvé via le lien sur la barre latérale vers la droite. C'est assez bien fait. J'ai eu du plaisir à essayer de réduire cela, mais je n'ai trouvé que 9 octets , un octet reposant sur les littéraux rationnels introduits dans ruby ​​2.1 (?).
blutorange
5

Python 2: 320 caractères

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)

Pourrait probablement être raccourci, mais je suis un peu novice dans ce domaine :)

Faire Nune variable gaspille 9 caractères mais je l'aime mieux de cette façon.

NicolasP
la source