-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStringToLambda.py
More file actions
115 lines (102 loc) · 3.34 KB
/
StringToLambda.py
File metadata and controls
115 lines (102 loc) · 3.34 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
import re
# Finds end of selected bracket in string
import math
def bracket_closer_pos(data, pos):
counter = 1
pos += 1
for c in data[pos:]:
if c == '(':
counter += 1
elif c == ')':
counter -= 1
if counter == 0:
return pos
else:
pos += 1
raise ValueError("String is incorrect")
def string_to_lambda(string):
from StringPreparation import prepare
s = prepare(string)
r, t = anc_string_to_lambda(s)
return r
operations = {
"+": lambda a, b: a + b,
"-": lambda a, b: a - b,
"*": lambda a, b: a * b,
"/": lambda a, b: a / b,
"^": lambda a, b: math.pow(a, b),
"log": lambda a, b: math.log(b, a),
"ln": lambda a, b: math.log(a),
"abs": lambda a, b: abs(a),
"sin": lambda a, b: math.sin(a),
"cos": lambda a, b: math.cos(a),
"tg": lambda a, b: math.tan(a),
"ctg": lambda a, b: 1 / math.tan(a),
"arcsin": lambda a, b: math.asin(a),
"arccos": lambda a, b: math.acos(a),
"arctg": lambda a, b: math.atan(a),
}
def anc_string_to_lambda(string):
if string == "":
return lambda x: 0, True
op, left, right = operation_split(string)
if op == "number":
return lambda x: float(left), True
if op == "x":
return lambda x: x, False
o = operations.get(op)
f, f_is_const = anc_string_to_lambda(left)
g, g_is_const = anc_string_to_lambda(right)
if f_is_const and g_is_const:
temp = o(f(0), g(0))
return lambda x: temp, True
elif f_is_const and not g_is_const:
temp = f(0)
return lambda x: o(temp, g(x)), False
elif not f_is_const and g_is_const:
temp = g(0)
return lambda x: o(f(x), temp), False
else:
return lambda x: o(f(x), g(x)), False
# Ancillary function for unary functions
def unary_operation_split(data):
if '0' <= data[0] <= '9':
return "number", data, ""
if data == "e":
return "number", "2.71828182846", ""
if data == "pi":
return "number", "3.14159265359", ""
if data[0] == 'x':
return "x", data, ""
unary_operators = ["abs", "sin", "cos", "tg", "ctg", "arcsin", "arccos", "arctg", "ln"]
for op in unary_operators:
if re.search("^" + op, data):
return op, data[len(op):].strip(), ""
if re.search("^log", data): # to repair
b = data.find("(")
e = bracket_closer_pos(data, b)+1
return "log", data[b:e].strip(), data[e:].strip()
raise ValueError("String is incorrect")
# Splits string of operation to (operator, left_argument, right,argument)
def operation_split(data):
data = data.strip()
if data[0] == '(' and bracket_closer_pos(data, 0) == len(data) - 1:
return operation_split(data[1:-1])
if data[0] == "-":
return "-", "0", data[1:]
binary_operators = ["+", "-", "*", "/", "^", ""]
op = ""
pos = 0
i = 0
while i < len(data):
if data[i] == '(':
i = bracket_closer_pos(data, i)
if data[i] in binary_operators:
if binary_operators.index(data[i]) < binary_operators.index(op):
op = data[i]
pos = i
i += 1
if op == "":
return unary_operation_split(data)
else:
return op, data[:pos], data[pos + 1:]