Реалізуйте графічний калькулятор


12

Було багато питань щодо калькуляторів; однак, не здається, що будь-які пов'язані із застосуванням графічного калькулятора.

Змагання

Ви повинні написати повну програму, яка приймає декілька формул як вхід зі STDIN і графікує їх до STDOUT. Введення прийматиме форму f1(x)=x^2-x-1. Там буде fсупроводжуватися числом 0-9 (включно), а потім (x)=, а потім по формулі на графіку. Ваша програма повинна мати можливість приймати вклад, графік, більше вводити, графік тощо.

Це код гольфу.

Ваш графік повинен мати діапазон осі X від -5 до 5, з роздільною здатністю не менше однієї точки кожні 1/2 одиниці. Вимоги по осі Y однакові. Це може здатися невеликим діапазоном порівняно із сучасними калькуляторами, але це, швидше за все, буде тривіально збільшувати це. На графіку повинна бути намальована вісь на них із відмітками у вигляді +цілих чисел.

Формулу слід оцінювати за нормальним порядком роботи. У цих формулах не буде жодних вертикальних асимптот / невизначених областей. Змінна завжди буде x. Якщо дві формули введені з однаковим номером рівняння, найдавнішу слід стерти та замінити новою формулою. Пусті формули повинні оцінюватися до нуля. Оскільки цілком ймовірно, що формула не завжди дає хороший кратний 1/2, ви повинні округлити до найближчої 1/2.

Коли формула схоплена, її рядок повинен формуватися з числа формули. Коли лінія перетинає вісь, вісь слід намалювати зверху. Коли дві лінії перетинаються один з одним, не має значення, що зображено.

Приклад введення

f1(x)=x+1

Вихідні дані

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

Вхідні дані

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

Вихідні дані

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

Вхідні дані

f1(x)=-x  

(зауважте, ваша програма може відхилити цей вхід і лише за винятком 0-x або x * -1, але це має бути задокументовано)

Вихідні дані

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

Відповіді:


5

Perl, 177 символів (+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}'

Згідно з цією мета-ниткою , я вважаю, що це повинно нараховувати загалом 178 символів.

Як рішення Рубі, я також використовую evalі заміна ^з **.

Аналіз входу одночасно є надзвичайно крихким та неймовірно надійним: f1(x)=його можна записати як f 1 ( x ) =або foo 1 bar =навіть просто 1=, але дуже дивні речі можуть трапитися, якщо ви заміните fте, що не є дійсним, безрезультатним твердженням Perl. Вас попередили

Інші подробиці інтерес включають спосіб вертикальної осі малюється, який використовує той факт , що побітовое виключає символів +і |є W. Очевидно, що це не буде працювати в системах EBCDIC.

Вихід надається в хеш масивів, а не в масив масивів - виявляється, що потрібно менше символів, щоб явно урізати хеш-ключі до цілих чисел, а потім перевести цикл на хеш-фрагмент, ніж потрібно, щоб гарантувати, що масив не є індексується з від’ємними значеннями. Я міг би поголити ще двох символів, якби не набридливий спосіб, коли Перл intобрізає негативні значення до нуля, що змусило мене нумерувати вихідні рядки від 2 до 22 замість 0 до 20, щоб уникнути округлення артефактів у верхньому краї площі виводу

Я використовую ліберальне перетворення рядка в число Perl при аналізі входу, де я використовую всю рядок 1(x)=як індекс масиву (він перетворюється на лише 1).

Я також міг би зберегти ще три символи (і зробити синтаксичний розбір трохи більш надійним), замінивши s/\d.*=/;/;$f[$&]=$_на /\d.*=/;$f[$&]=$', але тоді мені доведеться витратити стільки ж зайвих символів, щоб написати, $'як $'\''у одноцитованому рядку оболонки. Я припускаю, що технічно мені б не довелося рахувати це, але це виглядає як би обман.


6

Рубін, 200 символів

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

Проста реалізація рубіну з використанням стандартного оцінювача для виразів ( ^буде замінено таким чином, щоб приклади, наведені вище, спрацювали нормально). Він не дуже надійний і передбачає введення точно так, як зазначено в питанні.


На п'ятому рядку, ви могли б змінити , y*0.5щоб y/2і позбутися від двох персонажів? Я не знаю Рубі, тому я, можливо, не прав.
PhiNotPi

2
@PhiNotPi На жаль, це не працює. y/2робить ціле ділення.
Говард

Ви можете використовувати loop{}замість ()while 1?
дефш

Знайдено це за посиланням на бічній смузі на праву сторону. Це досить добре зроблено. Мені було весело, намагаючись отримати цей менший розмір, але я знайшов лише 9 байт , один байт спирався на раціональні літерали, введені в рубіні 2.1 (?).
blutorange

5

Python 2: 320 символів

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)

Можливо, може бути скорочено, але я трохи новачок у цьому :)

Створення Nзмінної втрачає 9 знаків, але мені це подобається краще.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.