Skip to content

Instantly share code, notes, and snippets.

@9999years
Created May 6, 2017 02:06
Show Gist options
  • Save 9999years/9d19a4c87cfc145a1c160281fa8c7b0b to your computer and use it in GitHub Desktop.
Save 9999years/9d19a4c87cfc145a1c160281fa8c7b0b to your computer and use it in GitHub Desktop.
import math
import re
def get_float(prompt):
return float(input(prompt))
# ok, this one is kinda complicated to describe
# scales a number val (assumed to be in the range of valmin to valmax)
# to the equivalent fractional distance from min to max
# eg if you have a percent value and you want it to be a byte val
# you could call scale(val, 0.0, 1.0, 0.0, 255.0)
def scale(val, valmin, valmax, outmin, outmax):
return (
(val - valmin) / (valmax - valmin)
* (outmax - outmin) + outmin
)
print("enter a formula to graph in terms of x")
print("functions like sin, tan, ln, floor, and sqrt are allowed")
print("as are pi and e. exponentiation is allowed (e.g. x^2) but for non-")
print("integer exponents e.g. pow(x, 2.2) should be used instead")
print("EXAMPLE: y(x) = 2sin(x)")
print("EXAMPLE: y(x) = ln(0.5x^2)")
print("EXAMPLE: y(x) = pow(x, 3.3)")
fn = input("y(x) = ")
if len(fn) is 0:
fn = "2sin(x)"
# replace stuff like 2tan(4x) with 2*tan(4*x)
fn = re.sub(r"(\d+)([a-zA-Z]+)", r"\1 * \2", fn)
# ln = log
fn = re.sub(r"ln", r"log", fn)
# replace stuff like tan(x) with math.tan(x), which python can evaluate
# sorry this is so long, please ignore, it's literally every math method
fn = re.sub(r"""\b(ceil|copysign|fabs|factorial|floor|fmod|frexp|fsum|isinf|
isnan|ldexp|modf|trunc|exp|expm1|log|log1p|log10|pow|sqrt|acos|asin|atan|
atan2|cos|hypot|sin|tan|degrees|radians|acosh|asinh|atanh|cosh|sinh|tanh|erf|
erfc|gamma|lgamma|pi|e)\b""", r"math.\1", fn)
#replace ^ with **
fn = re.sub(r"\^", r"**", fn)
coords = []
# window info for console output
win_w = 79
win_h = 23
win_cx = math.floor(win_w / 2)
win_cy = math.floor(win_h / 2)
# graph data
domain_min = -5
domain_max = 5
range_min = -5
range_max = 5
for i in range(0, win_w):
x = scale(i, 0, win_w, domain_min, domain_max)
try:
coords.append(eval(fn))
except ValueError:
# negative number in a log or root probably
coords.append(float("nan"))
# create win_h-element 2d array
graph = []
for i in range(0, win_h):
graph.append([])
for i in range(0, win_w):
# make sure we have space to work with
for j in range(0, win_h):
graph[j].append(" ")
# line for x axis
graph[win_cy][i] = "-"
# if we have a number to plot, plot it
if not math.isnan(coords[i]):
height = math.floor(scale(coords[i], range_min, range_max, 0, win_h))
if height > 0 and height < win_h:
graph[height][i] = "#"
for i in range(0, win_h):
graph[i][win_cx] = "|"
for i in range(domain_min, domain_max):
x_tick = math.floor(scale(i, domain_min, domain_max, 0, win_w))
graph[win_cy][x_tick] = "+"
graph[win_cy + 1][x_tick] = str(abs(i))
if i < 0 and x_tick > 0:
graph[win_cy + 1][x_tick - 1] = "-"
for i in range(range_min, range_max):
y_tick = math.floor(scale(i, range_min, range_max, 0, win_h))
graph[y_tick][win_cx] = "+"
graph[y_tick][win_cx + 3] = str(abs(i))
if i < 0 and y_tick > 0:
graph[y_tick][win_cx + 2] = "-"
# origin
graph[win_cy][win_cx] = "+"
for j in range(win_h - 1, -1, -1):
for i in range(0, win_w):
print(graph[j][i], end="")
print("\n", end="")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment