So I made this script for my calculator, so that I can just write whatever formula I want and the calculator would just ask for the missing pieces to do the calculations.
I made it so that it would be very easy to fill in, I just go to the end of the list, give it a name and the formula. That's it!
The working of it is as followed:
- User choses which topic/name to use
- The script checks how many formulas are under that name if it's greater than 1 he needs to make another choice for which formula to run
- The script will start searching for the variables that are needed to be filled in by the user and ask the user to give them a value, to achieve this I used
eval()
andexec()
. (It is a calculator used by me so I don't have security concerns and the runtimes were pretty great too) - It will print the answer
What could I have done better and if it was the right decision to make use of eval()
and exec()
functions? I needed a fast and a less complex way to just get what I want and they just felt like the perfect solution.
Here's the code:
from math import *
SWIDTH = 42
# Accessing shapes will happen by their index number
# The list is formed in the following structure [Name or "Mother", formula 1, formula 2, ...]
list_shapes = [
["cilinder", "pi*r^2*h", "2*r*h", "2*r*h + 2*pi*r^2"],
["kegel", "1/3*pi*r^2*h", "pi*r*a", "pi*r*a + pi*r^2"],
[
"afgeknokte kegel",
"1/3*pi*h*((r_1)^2+(r_2)^2+(r_1)*(r_2))",
"pi*(r_1+r_2)*a",
"pi*a*(r_1+r_2) + pi*((r_1)^2+(r_2)^2)",
],
["bol", "4/3*pi*r^3", "4*pi*r^2"],
["bolzone", "pi*(r_1)^2*h/2+pi*(r_2)^2*h/2+pi*h^3/6", "2*pi*r*h"],
["bolkap", "1/3*pi*h^2*(3*r-h)", "2*pi*r*h"],
["bolschil", "1/6*pi*h*k^2"],
["bolsector", "2/3*pi*r^2"],
["piramide", "1/3*G*h"],
["afgeknotte priamide", "1/3*h*(G+B+sqrt(B*G))"],
]
def Main():
for x in range(len(list_shapes)): # Prints the name of all contained shapes
print(x, list_shapes[x][0])
figur_num = int(input("Figuur= ")) # Select the number of the shape
print_shape_name(figur_num)
print_formulas(figur_num)
# If the mother contains 1 formula, it directly starts executing it
if (len(list_shapes[figur_num]) - 1) == 1:
formula_num = 1
else:
formula_num = int(input("Formule= "))
print("\n{}".format(list_shapes[figur_num][formula_num]))
solver(figur_num, formula_num)
# Prints the shapes name centered
def print_shape_name(figur_num):
shape_name = list_shapes[figur_num][0] # Takes the shape name
# Calculate the amount of spaces to center the name of the shape
spaces = int(SWIDTH / 2 - len(shape_name) / 2) * " "
print("\n{}{}".format(spaces, shape_name.upper()))
# Prints all the availible formulas of the shape
def print_formulas(figur_num):
# Starts counting by skipping the name
for x in range(len(list_shapes[figur_num][1:])):
# Fixes the array order by adding +1 to x (Number 0 is the mother already)
print("{}. {}".format(x + 1, list_shapes[figur_num][x + 1]))
def solver(figur_num, formula_num):
# "^" for powers in math means something else in Python, thereby we need to change all of them to "**" which is the right operator for this
formula = list_shapes[figur_num][formula_num].replace("^", "**")
while True:
try:
print("Antwoord: {}".format(eval(formula)))
break # Will break the function if the line above doesn't outputs error
except Exception as error:
var_error = str(error)
index2 = var_error.find("' ") # The name of the variables is always followed by "' "
# Index 1 is always 6 in the error string
variable = var_error[6:index2] + "=" + input(var_error[6:index2] + "= ")
exec(variable)
Main()
SWIDTH
is not defined. Also, what version of Python are you targeting? \$\endgroup\$