├── README.md ├── examples ├── desmos_example.png ├── example2.png ├── example2result.png └── result_example.png └── latex2python.py /README.md: -------------------------------------------------------------------------------- 1 | # Latex2Python 2 | 3 | Frustrated from typing out complex mathematical expressions with tons of brackets in Python? This simple program takes a Latex expression generated by a symbolic maths builder and converts it to clean, syntactically correct Python code. 4 | 5 | ## Usage 6 | 7 | Type out your maths quickly in SymboLab, Desmos etc. 8 | 9 | ![Example](examples/desmos_example.png) 10 | 11 | Highlight and Copy 12 | 13 | Run `latex2python.py` using `python latex2python.py` in the terminal, or just normally in an IDE 14 | 15 | Paste when prompted and hit Enter 16 | 17 | ![Example](examples/result_example.png) 18 | 19 | Done! 20 | 21 | ## Update - Support for variables 22 | 23 | ![Example](examples/example2.png) 24 | 25 | yields 26 | 27 | ![Example](examples/example2result.png) 28 | 29 | ## Requirements 30 | 31 | `python 3.` 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /examples/desmos_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwalone/Latex2Python/041bd7c40f40eaf9dc46e1113f3a9bad88745ea6/examples/desmos_example.png -------------------------------------------------------------------------------- /examples/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwalone/Latex2Python/041bd7c40f40eaf9dc46e1113f3a9bad88745ea6/examples/example2.png -------------------------------------------------------------------------------- /examples/example2result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwalone/Latex2Python/041bd7c40f40eaf9dc46e1113f3a9bad88745ea6/examples/example2result.png -------------------------------------------------------------------------------- /examples/result_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwalone/Latex2Python/041bd7c40f40eaf9dc46e1113f3a9bad88745ea6/examples/result_example.png -------------------------------------------------------------------------------- /latex2python.py: -------------------------------------------------------------------------------- 1 | import re 2 | import argparse 3 | 4 | 5 | symbols = { 6 | r'\\ ' : '', 7 | r'\\left\s*\|' : r'\\abs(', 8 | r'\\right\s*\|' : ')', 9 | r'\\left' : '', 10 | r'\\right' : '', 11 | r'\\cdot' : '*', 12 | r'\\times' : '*', 13 | r'\\div' : '/', 14 | ' ' : '', 15 | '{' : '(', 16 | '}' : ')', 17 | '\^' : '**' 18 | } 19 | 20 | ops = { 21 | r'\\log' : 'np.log10', 22 | r'\\ln' : 'np.log', 23 | r'\\sin' : 'np.sin', 24 | r'\\cos' : 'np.cos', 25 | r'\\tan' : 'np.tan', 26 | r'\\arcsin' : 'np.arcsin', 27 | r'\\arccos' : 'np.arccos', 28 | r'\\arctan' : 'np.arctan', 29 | r'\\sinh' : 'np.sinh', 30 | r'\\cosh' : 'np.cosh', 31 | r'\\tanh' : 'np.tanh', 32 | r'\\sqrt' : 'np.sqrt', 33 | r'\\exp' : 'np.exp', 34 | r'\\abs' : 'np.abs' 35 | } 36 | 37 | funs = [r'\\frac', r'\\log_'] 38 | 39 | consts = { 40 | r'\\pi' : 'np.pi', 41 | } 42 | 43 | def isint(s): 44 | if s == '.': 45 | return True 46 | else: 47 | try: 48 | int(s) 49 | return True 50 | except ValueError: 51 | return False 52 | 53 | 54 | def getCloseBr(s): 55 | openBr = 0 56 | for pos, char in enumerate(s): 57 | if char == '(': 58 | openBr += 1 59 | elif char == ')': 60 | openBr -= 1 61 | if openBr == 0: 62 | return pos 63 | break 64 | 65 | 66 | def repFunctions(f, s): 67 | 68 | if f == r'\\frac': 69 | 70 | while True: 71 | try: 72 | i = [m.start() for m in re.finditer(f, s)][0] 73 | except: 74 | break 75 | s_strip1 = s[i+len(f)-1:] 76 | pos1 = getCloseBr(s_strip1) 77 | s_strip2 = s_strip1[pos1+1:] 78 | pos2 = getCloseBr(s_strip2) 79 | s = s[:i] + '(' + s_strip1[:pos1+1] + '/' + s_strip2[:pos2+1] + ')' + s_strip2[pos2+1:] 80 | 81 | if f == r'\\log_': 82 | while True: 83 | try: 84 | i = [m.start() for m in re.finditer(f, s)][0] 85 | except: 86 | break 87 | s_strip = s[i+len(f)-1:] 88 | 89 | if s_strip[0] == '(': 90 | pos1 = getCloseBr(s_strip) 91 | base = s_strip[:pos1+1] 92 | pos2 = getCloseBr(s_strip[pos1+1:]) + pos1+1 93 | arg = s_strip[pos1+1:pos2+1] 94 | pos = pos2 95 | else: 96 | base = s_strip.split('(')[0] 97 | pos = getCloseBr(s_strip[len(base):]) + len(base) 98 | arg = s_strip[len(base):pos+1] 99 | s = s[:i] + '(np.log('+arg+')/np.log('+base+'))' + s_strip[pos+1:] 100 | 101 | return s 102 | 103 | 104 | 105 | def insMultiply(s): 106 | s_temp = s 107 | for v in ops.values(): 108 | s_temp = re.sub(v, '('*len(v), s_temp) 109 | for v in consts.values(): 110 | s_temp = re.sub(v, '('*(len(v)-1)+')', s_temp) 111 | ops_list = ['*', '/', '(', '+', '-', '_'] 112 | idx_list = [] 113 | for i, char in enumerate(s_temp): 114 | if char == '(': 115 | if s_temp[i-1] not in ops_list and i != 0: 116 | idx_list.append(i) 117 | 118 | elif char not in ops_list and char != ')' and i != 0: 119 | if isint(char) == False: 120 | if s_temp[i-1] not in ops_list: 121 | idx_list.append(i) 122 | #elif isint(char) == True: 123 | # if s_temp[i-1] not in ops_list and isint(s_temp[i-1]) == False: 124 | # idx_list.append(i) 125 | 126 | idx_list = list(set(idx_list)) 127 | idx_list.sort() 128 | for c, i in enumerate(idx_list): 129 | s = s[:i+c] + '*' + s[i+c:] 130 | return s 131 | 132 | def remBrackets(s): 133 | idx_list = [] 134 | for i, char in enumerate(s): 135 | if char == '(': 136 | if s[i-1] in ['+', '-', '/', '*', ')', '(', '_']: 137 | pos = getCloseBr(s[i:]) + i 138 | if len([1 for o in ['+', '-', '/', '*', ')', '(', '_'] if o in s[i+1:pos]]) == 0: 139 | idx_list.append(i) 140 | idx_list.append(pos) 141 | if s[i+1] == '(': 142 | pos2 = getCloseBr(s[i+1:]) + i+1 143 | if pos2 == pos - 1: 144 | idx_list.append(i+1) 145 | idx_list.append(pos2) 146 | 147 | 148 | idx_list = list(set(idx_list)) 149 | idx_list.sort() 150 | for c, i in enumerate(idx_list): 151 | s = s[:i-c] + '' + s[i-c + 1:] 152 | return s 153 | 154 | 155 | def main(): 156 | 157 | while True: 158 | 159 | s = input("Paste your expression: ") 160 | 161 | for k, v in symbols.items(): 162 | s = re.sub(k, v, s) 163 | 164 | for k, v in consts.items(): 165 | s = re.sub(k, v, s) 166 | 167 | for f in funs: 168 | s = repFunctions(f, s) 169 | 170 | for k, v in ops.items(): 171 | s = re.sub(k, v, s) 172 | 173 | 174 | 175 | s = insMultiply(s) 176 | 177 | s = remBrackets(s) 178 | 179 | print("result : " + s) 180 | 181 | 182 | if __name__ == "__main__": 183 | main() 184 | --------------------------------------------------------------------------------