Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
326 changes: 326 additions & 0 deletions Untitled.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import math\n",
"from collections import OrderedDict, defaultdict\n",
"from functions import functions"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"with open(\"functions.py\", 'w') as out:\n",
" out.writelines('import math \\n\\n')\n",
" out.writelines('functions = {\\n\\t')\n",
" \n",
" is_first = True\n",
" for key, item in math.__dict__.items():\n",
" try: \n",
" if str(item)[0] == '<' and key[0] != '_':\n",
" if not is_first:\n",
" out.writelines(\", \\n\\t'{}': lambda x: math.{}(x)\".format(key, key))\n",
" else:\n",
" out.writelines(\"'{}': lambda x: math.{}(x)\".format(key, key))\n",
" is_first = False\n",
" except:\n",
" continue\n",
" out.writelines('\\n}')"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"string = '8+cos(cos5+2+sin(cos6+cos7)*9)/9+cos8*5*5/9 - cos(8+8)'"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[[4, 'cos'], [8, 'cos'], [19, 'sin'], [23, 'cos'], [30, 'cos'], [43, 'cos']]"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"arithmetic = OrderedDict([\n",
" (\"+\", lambda x, y: x + y),\n",
" (\"-\", lambda x, y: x - y),\n",
" (\"*\", lambda x, y: x * y),\n",
" (\"/\", lambda x, y: x / y),\n",
" (\"//\",lambda x, y: x //y),\n",
" (\"%\", lambda x, y: x % y),\n",
" (\"^\", lambda x, y: x ^ y),\n",
"])\n",
"\n",
"comparison = OrderedDict([\n",
" (\"<\", lambda x, y: x + y),\n",
" (\"<=\", lambda x, y: x + y),\n",
" (\"==\", lambda x, y: x + y),\n",
" (\"!=\", lambda x, y: x + y),\n",
" (\">=\", lambda x, y: x + y),\n",
" (\">\", lambda x, y: x + y),\n",
"])\n",
"\n",
"\n",
"arithmetic_symbols = arithmetic.keys()\n",
"comparison_sympols = comparison.keys()\n",
"functions_names = functions.keys()\n",
"\n",
"\n",
"def check_brackets(row):\n",
" stack = []\n",
" for i_close, symbol in enumerate(row):\n",
" try:\n",
" if symbol == ')':\n",
" stack.pop() \n",
" elif symbol == '(':\n",
" stack.append('(')\n",
" if len(stack) == 0:\n",
" return i_close\n",
" except:\n",
" print(\"Error\")\n",
" return\n",
" \n",
"# return not bool(stack)\n",
"\n",
"def get_idx_func_list(expr):\n",
" func_idx = defaultdict(list)\n",
" for sub in functions_names:\n",
" if sub in expr:\n",
" sub_size = len(sub)\n",
" expr_ = expr\n",
" size_deleted = 0\n",
" while 1:\n",
" try:\n",
" index = expr_.index(sub) + size_deleted\n",
" size_deleted = len(expr[:index + sub_size])\n",
" expr_ = expr[index + sub_size:]\n",
" func_idx[sub].append(index)\n",
" except:\n",
" break\n",
" \n",
" idx_func = []\n",
" for func, idxs in func_idx.items():\n",
" for idx in idxs:\n",
" idx_func.append([idx, func])\n",
" \n",
" idx_func = sorted(idx_func, key=lambda x: x[0])\n",
" \n",
" return idx_func\n",
"\n",
"get_idx_func_list(string)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'8+0.19461946733844862/9+-0.14550003380861354*5*5/9 - -0.9576594803233847'"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"def solve_functions(expr):\n",
"\n",
" idx_func = get_idx_func_list(expr)\n",
" end = -1\n",
" new_expr = ''\n",
" while idx_func:\n",
" idx, func = idx_func.pop(0)\n",
" start = idx + len(func)\n",
" new_expr += expr[end + 1:idx]\n",
"# print(new_expr)\n",
"\n",
" len_content = check_brackets(expr[start:])\n",
" if len_content != 0:\n",
" end = start + len_content\n",
" is_expression_inside = False\n",
" \n",
" while idx_func:\n",
" if idx_func[0][0] < end:\n",
" is_expression_inside = True\n",
" idx_func.pop(0)\n",
" else:\n",
" break\n",
" \n",
" if is_expression_inside:\n",
" number_expr = solve_functions(expr[start+1:end]) \n",
" number = calc(number_expr)\n",
" else :\n",
" number = calc(expr[start+1:end])\n",
" \n",
"\n",
" else:\n",
" number_expr = ''\n",
" end = start-1\n",
" for char in expr[start:]:\n",
" if char.isdigit() or char == \".\" and \".\" not in number_expr:\n",
" number_expr += char\n",
" end += 1\n",
" else:\n",
" number = float(number_expr)\n",
" break\n",
" else:\n",
" number = float(number_expr)\n",
" new_expr += str( functions[func](number) )\n",
"\n",
" if not idx_func:\n",
" new_expr += expr[end +1 :]\n",
" \n",
" return new_expr\n",
" \n",
"solve_functions(string)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"def lex(expr):\n",
" \"\"\"\n",
" seperates numbers from symbols, recursively nests parens\n",
" \"\"\"\n",
" tokens = []\n",
" while expr: \n",
" char, *expr = expr\n",
" if char == \"(\":\n",
" try:\n",
" paren, expr = lex(expr)\n",
" tokens.append(paren)\n",
" except ValueError:\n",
" raise Exception(\"paren mismatch\")\n",
" elif char == \")\":\n",
" return tokens, expr\n",
" \n",
" elif char.isdigit() or char == \".\":\n",
" #number\n",
" try:\n",
" if tokens[-1] in arithmetic_symbols:\n",
" tokens.append(char) #start a new num\n",
" elif type(tokens[-1]) is list:\n",
" raise Exception(\"parens cannot be followed by numbers\")\n",
" #no support for 5(1+1) yet\n",
" else:\n",
" tokens[-1] += char #add to last num\n",
" except IndexError:\n",
" #if tokens is empty\n",
" tokens.append(char) #start first num\n",
" elif char in arithmetic_symbols:\n",
" tokens.append(char)\n",
" \n",
" elif char.isspace():\n",
" pass\n",
" else:\n",
" raise Exception(\"invalid charecter: \" + char)\n",
" return tokens\n"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Input? \n"
]
}
],
"source": [
"\n",
"def evaluate(tokens):\n",
" for symbol, func in arithmetic.items():\n",
" #try to find an operation to eval in order\n",
" try:\n",
" pos = tokens.index(symbol)\n",
"# print(symbol, pos)\n",
" #split the tokens by the operation and eval that\n",
" leftTerm = evaluate(tokens[:pos])\n",
" rightTerm = evaluate(tokens[pos + 1:])\n",
" return func(leftTerm, rightTerm)\n",
" #incidentially, return immediatly breaks all loops within the\n",
" # function\n",
" except ValueError:\n",
" pass\n",
" #index raises ValueError when it's not found\n",
" if len(tokens) is 1:\n",
" try:\n",
" #it must be a number\n",
" return float(tokens[0])\n",
" except TypeError:\n",
" #if it's not a number\n",
" return evaluate(tokens[0])\n",
" else:\n",
" raise Exception(\"bad expression: \" + tokens)\n",
"\n",
"def calc(expr):\n",
" return evaluate(lex(expr))\n",
" \n",
"while 1:\n",
" try:\n",
" print(calc(input(\"Input? \")))\n",
" except:\n",
" break"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
48 changes: 48 additions & 0 deletions functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import math

functions = {
'hypot': lambda x: math.hypot(x),
'ceil': lambda x: math.ceil(x),
'factorial': lambda x: math.factorial(x),
'cosh': lambda x: math.cosh(x),
'isnan': lambda x: math.isnan(x),
'erf': lambda x: math.erf(x),
'asin': lambda x: math.asin(x),
'modf': lambda x: math.modf(x),
'pow': lambda x: math.pow(x),
'isclose': lambda x: math.isclose(x),
'sqrt': lambda x: math.sqrt(x),
'atanh': lambda x: math.atanh(x),
'gcd': lambda x: math.gcd(x),
'sin': lambda x: math.sin(x),
'exp': lambda x: math.exp(x),
'lgamma': lambda x: math.lgamma(x),
'cos': lambda x: math.cos(x),
'expm1': lambda x: math.expm1(x),
'log1p': lambda x: math.log1p(x),
'gamma': lambda x: math.gamma(x),
'floor': lambda x: math.floor(x),
'frexp': lambda x: math.frexp(x),
'log10': lambda x: math.log10(x),
'trunc': lambda x: math.trunc(x),
'erfc': lambda x: math.erfc(x),
'tan': lambda x: math.tan(x),
'asinh': lambda x: math.asinh(x),
'log': lambda x: math.log(x),
'fabs': lambda x: math.fabs(x),
'radians': lambda x: math.radians(x),
'tanh': lambda x: math.tanh(x),
'isfinite': lambda x: math.isfinite(x),
'atan': lambda x: math.atan(x),
'acos': lambda x: math.acos(x),
'fmod': lambda x: math.fmod(x),
'atan2': lambda x: math.atan2(x),
'log2': lambda x: math.log2(x),
'isinf': lambda x: math.isinf(x),
'degrees': lambda x: math.degrees(x),
'sinh': lambda x: math.sinh(x),
'copysign': lambda x: math.copysign(x),
'ldexp': lambda x: math.ldexp(x),
'fsum': lambda x: math.fsum(x),
'acosh': lambda x: math.acosh(x)
}