-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils.py
More file actions
139 lines (111 loc) · 3.99 KB
/
utils.py
File metadata and controls
139 lines (111 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import re
import math
from typing import Optional, Dict, Any
def validate_equation(equation: str) -> bool:
if '=' not in equation:
return False
safe_pattern = r'^[0-9xX\+\-\*\/\^\(\)\=\s\.a-zA-Z_,!@#\$%\^&\*\?<>\[\]\{\}\|\~`]+$'
return bool(re.match(safe_pattern, equation))
def clean_input(text: str) -> str:
return ' '.join(text.strip().split())
def format_number(num: float, precision: int = 6) -> str:
if isinstance(num, complex):
real = format_number(num.real, precision)
imag = format_number(num.imag, precision)
if num.imag >= 0:
return f"{real}+{imag}i"
else:
return f"{real}{imag}i"
if num.is_integer():
return str(int(num))
formatted = f"{num:.{precision}f}"
if '.' in formatted:
formatted = formatted.rstrip('0').rstrip('.')
return formatted
def escape_markdown(text: str) -> str:
escape_chars = r'\_*[]()~`>#+-=|{}.!'
for char in escape_chars:
text = text.replace(char, f'\\{char}')
return text
def preprocess_equation_extended(equation: str) -> str:
original = equation
equation = equation.replace('^', '**')
equation = equation.replace('ln', 'log')
equation = re.sub(r'(\d)([a-zA-Z])', r'\1*\2', equation)
equation = re.sub(r'([a-zA-Z])(\d)', r'\1*\2', equation)
equation = re.sub(r'([a-zA-Z])([a-zA-Z])', r'\1*\2', equation)
equation = re.sub(r'(\))([a-zA-Z\d])', r'\1*\2', equation)
equation = re.sub(r'(\d)(\()', r'\1*\2', equation)
function_replacements = {
'sin': 'sympy.sin',
'cos': 'sympy.cos',
'tan': 'sympy.tan',
'cot': 'sympy.cot',
'sec': 'sympy.sec',
'csc': 'sympy.csc',
'asin': 'sympy.asin',
'acos': 'sympy.acos',
'atan': 'sympy.atan',
'sinh': 'sympy.sinh',
'cosh': 'sympy.cosh',
'tanh': 'sympy.tanh',
'sqrt': 'sympy.sqrt',
'exp': 'sympy.exp',
'log': 'sympy.log',
'ln': 'sympy.log',
'abs': 'sympy.Abs',
'floor': 'sympy.floor',
'ceil': 'sympy.ceil'
}
for old, new in function_replacements.items():
equation = re.sub(rf'\b{old}\b', new, equation)
equation = re.sub(r'\be\b', 'sympy.E', equation)
equation = re.sub(r'\bpi\b', 'sympy.pi', equation)
equation = re.sub(r'\|([^|]+)\|', r'sympy.Abs(\1)', equation)
return equation
def prepare_equation_for_display(equation: str) -> str:
replacements = {
'**': '²',
'^': '²',
'*': '×',
'/': '÷',
'sqrt': '√',
'pi': 'π',
'exp': 'e^',
'log': 'ln',
'sympy.': ''
}
for old, new in replacements.items():
equation = equation.replace(old, new)
return equation
def get_function_properties(func_str: str) -> Dict[str, Any]:
properties = {
'type': 'unknown',
'degree': None,
'periodic': False,
'symmetric': False,
'domain': 'ℝ',
'range': 'ℝ'
}
func_lower = func_str.lower()
if any(trig in func_lower for trig in ['sin', 'cos', 'tan', 'cot', 'sec', 'csc']):
properties['type'] = 'trigonometric'
properties['periodic'] = True
elif 'exp' in func_lower or 'e^' in func_lower:
properties['type'] = 'exponential'
properties['range'] = '(0, ∞)'
elif 'log' in func_lower or 'ln' in func_lower:
properties['type'] = 'logarithmic'
properties['domain'] = '(0, ∞)'
elif 'sqrt' in func_lower:
properties['type'] = 'radical'
properties['domain'] = '[0, ∞)'
properties['range'] = '[0, ∞)'
elif any(op in func_lower for op in ['^', '**']):
properties['type'] = 'polynomial'
match = re.search(r'\^(\d+)|\*\*(\d+)', func_lower)
if match:
properties['degree'] = int(match.group(1) or match.group(2))
if 'x^2' in func_lower or 'x**2' in func_lower:
properties['symmetric'] = True
return properties