Created
December 17, 2014 22:12
-
-
Save tylerneylon/bda5769357f35ff17833 to your computer and use it in GitHub Desktop.
Graph functions in your terminal.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/bin/lua | |
usage_str = [[ | |
Usage: | |
lgraph 'function of x' | |
Example: | |
lgraph 'x^2' | |
]] | |
Grapher = {xmin = -1, xmax = 1, ymin = -1, ymax = 1, ncols = 160, nrows = 50} | |
function Grapher:new () | |
return setmetatable({}, {__index = self}) | |
end | |
local function round(x) | |
return math.floor(x + 0.5) | |
end | |
-- This returns a *function* that maps [a1, b1] to [a2, b2]. | |
local function range_mapper(a1, b1, a2, b2) | |
return function (x) | |
local perc_from_a = (x - a1) / (b1 - a1) | |
return a2 + (b2 - a2) * perc_from_a | |
end | |
end | |
-- Makes a map self.char[col][row] = <nil or character to print>. | |
function Grapher:setup_char_table(eqn) | |
local f = loadstring('local x = ...; return ' .. eqn) | |
-- This will be a table of tables so that self.char[col][row] is either | |
-- nil or the character to print at that location. | |
self.char = {} | |
local y_to_row = range_mapper(self.ymin, self.ymax, self.nrows, 1) | |
local col_to_x = range_mapper(1, self.ncols, self.xmin, self.xmax) | |
for col = 1, self.ncols do | |
local y = f(col_to_x(col)) | |
local row = round(y_to_row(y)) | |
if self.char[col] == nil then self.char[col] = {} end | |
self.char[col][row] = 'o' | |
end | |
end | |
function Grapher:graph(eqn) | |
self:setup_char_table(eqn) | |
for row = 1, self.nrows do | |
for col = 1, self.ncols do | |
io.write(self.char[col][row] or ' ') | |
end | |
io.write('\n') | |
end | |
end | |
AxisGrapher = Grapher:new() | |
function AxisGrapher:graph(eqn) | |
self:setup_char_table(eqn) -- This part is the same. | |
local zero_col = round(range_mapper(self.xmin, self.xmax, 1, self.ncols)(0)) | |
local zero_row = round(range_mapper(self.ymin, self.ymax, self.nrows, 1)(0)) | |
for row = 1, self.nrows do | |
for col = 1, self.ncols do | |
local c = self.char[col][row] | |
if not c and row == zero_row then c = '-' end | |
if not c and col == zero_col then c = '|' end | |
io.write(c or ' ') | |
end | |
io.write('\n') | |
end | |
end | |
if not arg[1] or (arg[1] == '-a' and not arg[2]) then | |
print(usage_str) | |
os.exit(0) | |
end | |
if arg[1] == '-a' then | |
g = AxisGrapher:new() | |
arg[1] = arg[2] | |
else | |
g = Grapher:new() | |
end | |
g:graph(arg[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I made this for a Lua tutorial video I'm working on. Its purpose is to illustrate how to handle simple object-oriented patterns in Lua.
Oh, you can also graph things with it. Here's an example:
I modified the
ncols
andnrows
values so the above example will make sense when viewed on this gist page.