# Equation Graphing (#176)

**URL:** <https://www.ruby-forum.com/t/equation-graphing-176/147804>\
**Category:** Ruby\
**Created:** [September 5, 2008, 4:08pm UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804 "2008-09-05T16:08:34Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 5, 2008, 4:08pm UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804/1 "2008-09-05T16:08:34Z")

</div>

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Q. 2:

1. Please do not post any solutions or spoiler discussion for this  
quiz until 48 hours have passed from the time on this message.

2. Support Ruby Q. 2 by submitting ideas as often as you can! (A  
permanent, new website is in the works for Ruby Q. 2. Until then,  
please visit the temporary website at

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem  
helps everyone on Ruby T. follow the discussion. Please reply to  
the original quiz message, if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

This week’s quiz idea provided and written by Martin DeMello.

## Equation Graphing (#176)

Back when the world was shiny and new, and BBC Basic my language of  
choice and necessity, one of the fun little programs I wrote was a  
simple equation grapher. Two things that made it simple were (i) the  
ever-useful EVAL function, and (ii) the almost trivial ability to pick  
a colour and a pair of coordinates and put a friendly glowing pixel  
onto the screen. Instant gratification writ large. Well, anything that  
Basic can do, Ruby should be able to, so your task this week is to  
whip out your favourite graphics toolkit or library and write a  
program that

1. Asks for a function of one variable, x
2. Asks for the region of the graph to display (xmin, xmax, ymin, ymax)
3. Plots the graph

You can trust the user to input a syntactically correct function, but  
don’t forget that it might behave badly for certain values of x (e.g.  
1/x where x=0). Style points for making the main loop look trivial 🙂

Here’s a neat little online grapher you can use to visually check your  
output: [http://www.walterzorn.com/grapher/grapher\_e.htm](http://www.walterzorn.com/grapher/grapher_e.htm).

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 7, 2008, 4:28pm UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804/2 "2008-09-07T16:28:54Z")

</div>

> ## Equation Graphing (#176)

…

> You can trust the user to input a syntactically correct function, but  
> don’t forget that it might behave badly for certain values of x (e.g.  
> 1/x where x=0). Style points for making the main loop look trivial 🙂

I went for style points. 🙂  
1/x where x = 0 is handled nicely too.

graph.rb:  
#!/usr/bin/ruby

def usage  
puts "USAGE: #{File.basename($0)}   
"  
exit 42  
end

eq = ARGV.shift || usage  
usage unless ARGV.length == 4

cmd = “set xr [%f:%f]; set yr [%f:%f]; set tit ‘%s’; plot %s w li  
notitle”

IO.popen(“gnuplot -persist”, “w”) do |plot|  
plot.puts cmd % [ARGV.collect { |a| a.to\_f }, eq, eq].flatten  
end

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 8, 2008, 5:16pm UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804/3 "2008-09-08T17:16:12Z")

</div>

On Fri, Sep 5, 2008 at 10:01 AM, Matthew M. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> whip out your favourite graphics toolkit or library and write a  
> program that
> 
> 1. Asks for a function of one variable, x
> 2. Asks for the region of the graph to display (xmin, xmax, ymin, ymax)
> 3. Plots the graph

I didn’t follow the requirements, but inspired by the quiz did a  
little bit using my favorite graphics (none;-):

def grapher xmin, ymin, xmax, ymax, &function  
ymax.downto(ymin) do |y|  
xmin.upto(xmax) do |x|  
begin  
print (function.call(x, y) ? ‘#’ : ‘+’)  
rescue  
print “X”  
end  
end  
print “\n”  
end  
print “\n”  
end

grapher(0, 0, 40, 10){|x,y| x == y}  
grapher(0, 0, 40, 10){|x,y| 2 \>= y**2 / x}  
grapher(0, -5, 60, 10){|x,y| y == (5 + Math.sin(x) \* 5).to\_i}  
grapher(-10, -5, 70, 10){|x,y| y**2 == x}

Output:

++++++++++#++++++++++++++++++++++++++++++  
+++++++++#+++++++++++++++++++++++++++++++  
++++++++#++++++++++++++++++++++++++++++++  
+++++++#+++++++++++++++++++++++++++++++++  
++++++#++++++++++++++++++++++++++++++++++  
+++++#+++++++++++++++++++++++++++++++++++  
++++#++++++++++++++++++++++++++++++++++++  
+++#+++++++++++++++++++++++++++++++++++++  
++#++++++++++++++++++++++++++++++++++++++  
+#+++++++++++++++++++++++++++++++++++++++  
#++++++++++++++++++++++++++++++++++++++++

X+++++++++++++++++++++++++++++++++#######  
X+++++++++++++++++++++++++++#############  
X+++++++++++++++++++++###################  
X++++++++++++++++########################  
X++++++++++++############################  
X++++++++################################  
X+++++###################################  
X+++#####################################  
X+#######################################  
X########################################  
X########################################

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+##+++++#+++++#+++++##+++++#+++++#+++++#+++++##+++++#+++++#++  
+++++++#+++++++#++++++++++#+++++++++++++#++++++++++#+++++++#+  
+++++++++#+++#++++++++++++++++++#+#++++++++++++++++++++++#+++  
++++++++++++++++++++++++++++#+++++++++#++++++++++++++#+++++++  
#++#+++++++++++++++#++++++++++++++++++++++++#++#+++++++++++++  
++++++++++++++++++++++#++#+++++++++++++++#+++++++++++++++++++  
++++++#+++++++++#+++++++++++++++++++++++++++++++++#+++++++++#  
++++++++++#+#++++++++++++++++++#+++#++++++++++++++++++#+#++++  
++++#+++++++++++++#++++++++++#+++++++#++++++++++#++++++++++++  
+++++#+++++#+++++#+++++##+++++#+++++#+++++##+++++#+++++#+++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#++++++  
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++#+++++++++++++++++++++  
++++++++++++++++++++++++++++++++++++++++++++++#++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++#+++++++++++++++++++++++++++++++++++++++++++++  
++++++++++++++++++++++++++#++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
++++++++++++++#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
++++++++++#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
++++++++++++++#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++  
++++++++++++++++++++++++++#++++++++++++++++++++++++++++++++++++++++++++++++++++++  
+++++++++++++++++++++++++++++++++++#+++++++++++++++++++++++++++++++++++++++++++++

[http://github.com/fjc/rubyquiz/tree/master/176.rb](http://github.com/fjc/rubyquiz/tree/master/176.rb)

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 10, 2008, 8:23am UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804/4 "2008-09-10T08:23:16Z")

</div>

Here’s my solution, using \_why’s wonderful little shoes toolkit. Run  
like

shoes graph.rb “x\*x; -5; 5; 0; 25”

The args are “fn; xmin; xmax; ymin; ymax”

I tried to make the code as straightforward as possible, to recapture  
the feel of the old Basic days. A few inevitable complications, due to  
shoes being a work in progress: the Grapher class is to work around  
scoping quirks, and the range check is due to a bug that doesn’t let  
the exception handler catch an overflowing Bignum -\> long conversion  
in the canvas code (it would’ve been nice to simply draw to a point  
off-canvas and let the drawing engine cope). Also shoes’s argv  
handling code puts the filename in ARGV[0] and doesn’t like negative  
numbers as plain command line args (they are treated as shoes args),  
so a single quoted string was the simplest thing that worked.

#------------------------------------------------------------------------------------------------------

# ARGV[0] is the filename, since we launch via shoes graph.rb args

ARGV.shift  
args = ARGV[0].split(";").map {|i| i.chomp}  
F = args.shift  
Xmin, Xmax, Ymin, Ymax = args.map {|i| i.to\_f}

X = Y = 800

XScale = X \* 1.0/(Xmax - Xmin)  
YScale = Y \* 1.0/(Ymax - Ymin)

class Grapher  
def at(x,y)  
[((x -Xmin)\* XScale).to\_i, Y - ((y - Ymin) \* YScale).to\_i] rescue  
nil  
end

def bounded?(x,y)  
x && y && 0 \<= x && x \<= X && 0 \<= y && y \<= Y  
end

def fn(x)  
y = eval(F)  
end  
end

Shoes.app :height =\> Y, :width =\> X do  
g = Grapher.new  
background rgb(255, 255, 255)

fill white  
stroke black  
strokewidth 1  
u, v = nil  
Xmin.step(Xmax, (Xmax - Xmin)/(X\*1.0)) {|i|  
begin  
x0, y0 = g.at(u,v)  
u, v = i, g.fn(i)  
x, y = g.at(u,v)  
if g.bounded?(x,y) and g.bounded?(x0,y0)  
line(x0, y0, x, y)  
end  
rescue  
end  
}  
end

---

<div class="post-metadata">

**Author:** ![mansfiem](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/fbc32d/32.png) [@mansfiem](https://www.ruby-forum.com/u/mansfiem)\
**Post date:** [September 11, 2008, 9:57am UTC](https://www.ruby-forum.com/t/equation-graphing-176/147804/5 "2008-09-11T09:57:41Z")

</div>

Hello

I think this is the time to show what RubyX11 can do.

You need the X11 directory from the RubyX11-0.6.pre1, ruby 1.8, and an X  
server.

The program is not as simple as with Shoes but it requires no binary  
extension - you could run it in JRuby as well.

Unfortunately RubyX11 is not complete, and likely will never be. As I  
understand it people went from server-side font rendering to  
client-side font rendering for X11 applications. This means that you  
cannot do the font rendering effectively to a remote display, the  
letters rendered by different applications suck in different ways, and  
you cannot write a simple client library for X that would also render  
text reasonably.

OK, enough complaints about lack of design in X protocols.

You can find the program attached. If you run it without parameters it  
asks for them interactively in the terminal.

It is sort of a cheat - the X11 interfacing is merged form two RubyX11  
examples, I only had to write the method that calculates the points of  
the graph and fix window resizing.

Thanks

Michal
