实施图形计算器


12

涉及计算器的问题很多。但是,似乎没有涉及实现图形计算器的事情。

挑战

您将要编写一个完整的程序,该程序将多个公式用作来自STDIN的输入并将其图形化到STDOUT。输入将采用形式f1(x)=x^2-x-1f后面会有一个数字0-9(含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

Answers:


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

对于每个meta线程,我相信总共应该算作178个字符。

像Ruby解决方案一样,我也在使用eval并替换^**

输入解析同时非常脆弱和难以置信:f1(x)=可以写为f 1 ( x ) =or foo 1 bar =或什至just 1=,但是如果f用无效的,无副作用的Perl语句替换,可能会发生非常奇怪的事情。你被警告了。

感兴趣的其他详细信息包括垂直轴绘制方式,它利用一个事实,即字符的按位异或+|W。显然,这在EBCDIC系统上不起作用。

输出呈现为数组的散列,而不是数组的散列-事实证明,将散列键显式地截断为整数,然后遍历散列切片所花费的字符数少于确保数组不是数组所需要的字符用负值索引。如果不是因为Perl的恼人方式int将负值截断为零,我可以再删除两个字符,这迫使我将输出行从2到22而不是0到20进行编号,以避免在顶部边缘舍入伪像输出区域的大小。

我确实在输入解析中使用了Perl的自由字符串到数字的转换,在这里我将整个字符串1(x)=用作数组索引(将其转换为1)。

我可能还可以节省三个字符(并进行解析稍微更强大的),用s/\d.*=/;/;$f[$&]=$_/\d.*=/;$f[$&]=$',但后来我不得不花费相同数量的额外字符写入$'作为$'\''一个单引号shell字符串。我想从技术上讲我不必数这些,但是感觉有点像作弊。


6

Ruby,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.5y/2两个字符吗?我不了解Ruby,所以我可能不对。
PhiNotPi 2011年

2
@PhiNotPi不幸的是,这行不通。y/2进行整数除法。
霍华德

可以loop{}代替使用()while 1吗?
2012年

通过右侧边栏上的链接找到了它。这做得很好。我试图将其减小到一个有趣的程度,但是我只发现了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个字符,但我更喜欢这种方式。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.