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


12

Было много вопросов, связанных с калькуляторами; однако, похоже, что это не связано с реализацией графического калькулятора.

Соревнование

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

Это код гольф.

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

Формула должна быть оценена с нормальным порядком работы. В этих формулах не будет никаких вертикальных асимптот / неопределенных областей. Переменная всегда будет х. Если две формулы вводятся с одним и тем же номером уравнения, самую старую следует удалить и заменить новой формулой. Пустые формулы должны оцениваться до нуля. Поскольку вполне вероятно, что формула не всегда дает хороший кратный 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 символов.

Как и решение Ruby, я также использую evalи заменяю ^на **.

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

Другие детали, представляющие интерес, включают способ рисования вертикальной оси, который использует тот факт, что битовое XOR символов +и |является W. Очевидно, что это не будет работать в системах EBCDIC.

Вывод выводится в хэш массивов, а не в массив массивов - получается, что для явного усечения ключей хеш-функции до целых чисел требуется меньше символов, а затем цикл по фрагменту хеш-функции, чем для гарантии того, что массив не индексируется с отрицательными значениями. Я мог бы сбрить еще два символа, если бы не раздражающий способ, которым Perl 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

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


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

2
@PhiNotPi К сожалению, это не сработает. y/2делает целочисленное деление.
Говард

Вы можете использовать loop{}вместо ()while 1?
defhlt

Нашел это по ссылке на боковой панели справа. Это довольно хорошо сделано. Я немного повеселился, пытаясь получить это меньше, но я нашел только 9 байтов , один байт полагался на рациональные литералы, введенные в ruby ​​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.