spagestic commited on
Commit
9b3b8c8
·
1 Parent(s): 6c13437

algebra & arithmetic modularized

Browse files
maths/algebra/algebra.py CHANGED
@@ -1,213 +0,0 @@
1
- """
2
- Basic algebra operations for middle school level.
3
- """
4
- import cmath
5
- from fractions import Fraction
6
-
7
- def solve_linear_equation(a, b):
8
- """
9
- Solve the equation ax = b for x.
10
- Returns the value of x.
11
- """
12
- if a == 0:
13
- if b == 0:
14
- return "Infinite solutions"
15
- return "No solution"
16
- return b / a
17
-
18
- def evaluate_expression(a, b, c, x):
19
- """
20
- Evaluate the expression ax² + bx + c for a given value of x.
21
- """
22
- return a * (x ** 2) + b * x + c
23
-
24
-
25
- def solve_quadratic(a: float, b: float, c: float, return_format: str = "string"):
26
- """
27
- Solve the quadratic equation ax^2 + bx + c = 0.
28
-
29
- Args:
30
- a: Coefficient of x^2.
31
- b: Coefficient of x.
32
- c: Constant term.
33
- return_format: Format of return value - "string" for human-readable string
34
- or "dict" for dictionary with roots and vertex.
35
-
36
- Returns:
37
- Either a string representing the solutions or a dictionary with roots and vertex.
38
- """
39
- if a == 0:
40
- if b == 0:
41
- result = "Not a valid equation (a and b cannot both be zero)." if c != 0 else "Infinite solutions (0 = 0)"
42
- return result if return_format == "string" else {"error": result}
43
- # Linear equation: bx + c = 0 -> x = -c/b
44
- root = -c/b
45
- if return_format == "string":
46
- return f"Linear equation: x = {root}"
47
- else:
48
- return {"roots": (root, None), "vertex": None}
49
-
50
- # Calculate vertex
51
- vertex_x = -b / (2 * a)
52
- vertex_y = c - (b**2 / (4 * a))
53
- vertex = (vertex_x, vertex_y)
54
-
55
- # Calculate discriminant and roots
56
- delta = b**2 - 4*a*c
57
-
58
- if return_format == "dict":
59
- # Use cmath for complex roots
60
- discriminant = cmath.sqrt(b**2 - 4*a*c)
61
- root1 = (-b + discriminant) / (2 * a)
62
- root2 = (-b - discriminant) / (2 * a)
63
-
64
- # Convert to fraction if possible
65
- if root1.imag == 0 and root2.imag == 0:
66
- root1 = Fraction(root1.real).limit_denominator()
67
- root2 = Fraction(root2.real).limit_denominator()
68
-
69
- return {"roots": (root1, root2), "vertex": vertex}
70
-
71
- # For string format, handle different cases
72
- if delta > 0:
73
- x1 = (-b + delta**0.5) / (2*a)
74
- x2 = (-b - delta**0.5) / (2*a)
75
- # Try to convert to fractions for cleaner display
76
- try:
77
- x1_frac = Fraction(x1).limit_denominator()
78
- x2_frac = Fraction(x2).limit_denominator()
79
- return f"Two distinct real roots: x1 = {x1_frac}, x2 = {x2_frac}\nVertex at: {vertex}"
80
- except:
81
- return f"Two distinct real roots: x1 = {x1}, x2 = {x2}\nVertex at: {vertex}"
82
- elif delta == 0:
83
- x1 = -b / (2*a)
84
- try:
85
- x1_frac = Fraction(x1).limit_denominator()
86
- return f"One real root (repeated): x = {x1_frac}\nVertex at: {vertex}"
87
- except:
88
- return f"One real root (repeated): x = {x1}\nVertex at: {vertex}"
89
- else: # delta < 0
90
- real_part = -b / (2*a)
91
- imag_part = (-delta)**0.5 / (2*a)
92
- return f"Two complex roots: x1 = {real_part} + {imag_part}i, x2 = {real_part} - {imag_part}i\nVertex at: {vertex}"
93
-
94
-
95
- def simplify_radical(number: int) -> str:
96
- """
97
- Simplifies a radical (square root) to its simplest form (e.g., sqrt(12) -> 2*sqrt(3)).
98
-
99
- Args:
100
- number: The number under the radical.
101
-
102
- Returns:
103
- A string representing the simplified radical.
104
- """
105
- if not isinstance(number, int):
106
- return "Input must be an integer."
107
- if number < 0:
108
- return "Cannot simplify the square root of a negative number with this function."
109
- if number == 0:
110
- return "0"
111
-
112
- i = 2
113
- factor = 1
114
- remaining = number
115
- while i * i <= remaining:
116
- if remaining % (i * i) == 0:
117
- factor *= i
118
- remaining //= (i*i)
119
- # Restart checking with the same i in case of factors like i^4, i^6 etc.
120
- continue
121
- i += 1
122
-
123
- if factor == 1:
124
- return f"sqrt({remaining})"
125
- if remaining == 1:
126
- return str(factor)
127
- return f"{factor}*sqrt({remaining})"
128
-
129
-
130
- def polynomial_operations(poly1_coeffs: list[float], poly2_coeffs: list[float], operation: str) -> str:
131
- """
132
- Performs addition, subtraction, or multiplication of two polynomials.
133
- Polynomials are represented by lists of coefficients in descending order of power.
134
- Example: [1, -2, 3] represents x^2 - 2x + 3.
135
-
136
- Args:
137
- poly1_coeffs: Coefficients of the first polynomial.
138
- poly2_coeffs: Coefficients of the second polynomial.
139
- operation: "add", "subtract", or "multiply".
140
-
141
- Returns:
142
- A string representing the resulting polynomial or an error message.
143
- """
144
- if not all(isinstance(c, (int, float)) for c in poly1_coeffs) or \
145
- not all(isinstance(c, (int, float)) for c in poly2_coeffs):
146
- return "Error: All coefficients must be numbers."
147
-
148
- if not poly1_coeffs:
149
- poly1_coeffs = [0]
150
- if not poly2_coeffs:
151
- poly2_coeffs = [0]
152
-
153
- op = operation.lower()
154
-
155
- if op == "add":
156
- len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
157
- max_len = max(len1, len2)
158
- p1 = [0]*(max_len - len1) + poly1_coeffs
159
- p2 = [0]*(max_len - len2) + poly2_coeffs
160
- result_coeffs = [p1[i] + p2[i] for i in range(max_len)]
161
- elif op == "subtract":
162
- len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
163
- max_len = max(len1, len2)
164
- p1 = [0]*(max_len - len1) + poly1_coeffs
165
- p2 = [0]*(max_len - len2) + poly2_coeffs
166
- result_coeffs = [p1[i] - p2[i] for i in range(max_len)]
167
- elif op == "multiply":
168
- len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
169
- result_coeffs = [0] * (len1 + len2 - 1)
170
- for i in range(len1):
171
- for j in range(len2):
172
- result_coeffs[i+j] += poly1_coeffs[i] * poly2_coeffs[j]
173
- else:
174
- return "Error: Invalid operation. Choose 'add', 'subtract', or 'multiply'."
175
-
176
- # Format the result string
177
- if not result_coeffs or all(c == 0 for c in result_coeffs):
178
- return "0"
179
-
180
- terms = []
181
- degree = len(result_coeffs) - 1
182
- for i, coeff in enumerate(result_coeffs):
183
- power = degree - i
184
- if coeff == 0:
185
- continue
186
-
187
- term_coeff = ""
188
- if coeff == 1 and power != 0:
189
- term_coeff = ""
190
- elif coeff == -1 and power != 0:
191
- term_coeff = "-"
192
- else:
193
- term_coeff = str(coeff)
194
- if isinstance(coeff, float) and coeff.is_integer():
195
- term_coeff = str(int(coeff))
196
-
197
-
198
- if power == 0:
199
- terms.append(term_coeff)
200
- elif power == 1:
201
- terms.append(f"{term_coeff}x")
202
- else:
203
- terms.append(f"{term_coeff}x^{power}")
204
-
205
- # Join terms, handling signs
206
- result_str = terms[0]
207
- for term in terms[1:]:
208
- if term.startswith("-"):
209
- result_str += f" - {term[1:]}"
210
- else:
211
- result_str += f" + {term}"
212
-
213
- return result_str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
maths/algebra/algebra_interface.py CHANGED
@@ -1,8 +1,9 @@
1
  import gradio as gr
2
- from maths.algebra.algebra import (
3
- solve_linear_equation, evaluate_expression, solve_quadratic,
4
- simplify_radical, polynomial_operations
5
- )
 
6
 
7
  # Middle School Math Tab
8
  solve_linear_equation_interface = gr.Interface(
 
1
  import gradio as gr
2
+ from maths.algebra.solve_linear_equation import solve_linear_equation
3
+ from maths.algebra.evaluate_expression import evaluate_expression
4
+ from maths.algebra.solve_quadratic import solve_quadratic
5
+ from maths.algebra.simplify_radical import simplify_radical
6
+ from maths.algebra.polynomial_operations import polynomial_operations
7
 
8
  # Middle School Math Tab
9
  solve_linear_equation_interface = gr.Interface(
maths/algebra/evaluate_expression.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ """
2
+ Evaluate the expression ax² + bx + c for a given value of x.
3
+ """
4
+ def evaluate_expression(a, b, c, x):
5
+ return a * (x ** 2) + b * x + c
maths/algebra/polynomial_operations.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Performs addition, subtraction, or multiplication of two polynomials.
3
+ Polynomials are represented by lists of coefficients in descending order of power.
4
+ Example: [1, -2, 3] represents x^2 - 2x + 3.
5
+ """
6
+ def polynomial_operations(poly1_coeffs: list[float], poly2_coeffs: list[float], operation: str) -> str:
7
+ if not all(isinstance(c, (int, float)) for c in poly1_coeffs) or \
8
+ not all(isinstance(c, (int, float)) for c in poly2_coeffs):
9
+ return "Error: All coefficients must be numbers."
10
+ if not poly1_coeffs:
11
+ poly1_coeffs = [0]
12
+ if not poly2_coeffs:
13
+ poly2_coeffs = [0]
14
+ op = operation.lower()
15
+ if op == "add":
16
+ len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
17
+ max_len = max(len1, len2)
18
+ p1 = [0]*(max_len - len1) + poly1_coeffs
19
+ p2 = [0]*(max_len - len2) + poly2_coeffs
20
+ result_coeffs = [p1[i] + p2[i] for i in range(max_len)]
21
+ elif op == "subtract":
22
+ len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
23
+ max_len = max(len1, len2)
24
+ p1 = [0]*(max_len - len1) + poly1_coeffs
25
+ p2 = [0]*(max_len - len2) + poly2_coeffs
26
+ result_coeffs = [p1[i] - p2[i] for i in range(max_len)]
27
+ elif op == "multiply":
28
+ len1, len2 = len(poly1_coeffs), len(poly2_coeffs)
29
+ result_coeffs = [0] * (len1 + len2 - 1)
30
+ for i in range(len1):
31
+ for j in range(len2):
32
+ result_coeffs[i+j] += poly1_coeffs[i] * poly2_coeffs[j]
33
+ else:
34
+ return "Error: Invalid operation. Choose 'add', 'subtract', or 'multiply'."
35
+ if not result_coeffs or all(c == 0 for c in result_coeffs):
36
+ return "0"
37
+ terms = []
38
+ degree = len(result_coeffs) - 1
39
+ for i, coeff in enumerate(result_coeffs):
40
+ power = degree - i
41
+ if coeff == 0:
42
+ continue
43
+ term_coeff = ""
44
+ if coeff == 1 and power != 0:
45
+ term_coeff = ""
46
+ elif coeff == -1 and power != 0:
47
+ term_coeff = "-"
48
+ else:
49
+ term_coeff = str(coeff)
50
+ if isinstance(coeff, float) and coeff.is_integer():
51
+ term_coeff = str(int(coeff))
52
+ if power == 0:
53
+ terms.append(term_coeff)
54
+ elif power == 1:
55
+ terms.append(f"{term_coeff}x")
56
+ else:
57
+ terms.append(f"{term_coeff}x^{power}")
58
+ result_str = terms[0]
59
+ for term in terms[1:]:
60
+ if term.startswith("-"):
61
+ result_str += f" - {term[1:]}"
62
+ else:
63
+ result_str += f" + {term}"
64
+ return result_str
maths/algebra/simplify_radical.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Simplifies a radical (square root) to its simplest form (e.g., sqrt(12) -> 2*sqrt(3)).
3
+ """
4
+ def simplify_radical(number: int) -> str:
5
+ if not isinstance(number, int):
6
+ return "Input must be an integer."
7
+ if number < 0:
8
+ return "Cannot simplify the square root of a negative number with this function."
9
+ if number == 0:
10
+ return "0"
11
+ i = 2
12
+ factor = 1
13
+ remaining = number
14
+ while i * i <= remaining:
15
+ if remaining % (i * i) == 0:
16
+ factor *= i
17
+ remaining //= (i*i)
18
+ continue
19
+ i += 1
20
+ if factor == 1:
21
+ return f"sqrt({remaining})"
22
+ if remaining == 1:
23
+ return str(factor)
24
+ return f"{factor}*sqrt({remaining})"
maths/algebra/solve_linear_equation.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Solve the equation ax = b for x.
3
+ """
4
+ def solve_linear_equation(a, b):
5
+ if a == 0:
6
+ if b == 0:
7
+ return "Infinite solutions"
8
+ return "No solution"
9
+ return b / a
maths/algebra/solve_quadratic.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Solve the quadratic equation ax^2 + bx + c = 0.
3
+ """
4
+ import cmath
5
+ from fractions import Fraction
6
+
7
+ def solve_quadratic(a: float, b: float, c: float, return_format: str = "string"):
8
+ if a == 0:
9
+ if b == 0:
10
+ result = "Not a valid equation (a and b cannot both be zero)." if c != 0 else "Infinite solutions (0 = 0)"
11
+ return result if return_format == "string" else {"error": result}
12
+ root = -c/b
13
+ if return_format == "string":
14
+ return f"Linear equation: x = {root}"
15
+ else:
16
+ return {"roots": (root, None), "vertex": None}
17
+ vertex_x = -b / (2 * a)
18
+ vertex_y = c - (b**2 / (4 * a))
19
+ vertex = (vertex_x, vertex_y)
20
+ delta = b**2 - 4*a*c
21
+ if return_format == "dict":
22
+ discriminant = cmath.sqrt(b**2 - 4*a*c)
23
+ root1 = (-b + discriminant) / (2 * a)
24
+ root2 = (-b - discriminant) / (2 * a)
25
+ if root1.imag == 0 and root2.imag == 0:
26
+ root1 = Fraction(root1.real).limit_denominator()
27
+ root2 = Fraction(root2.real).limit_denominator()
28
+ return {"roots": (root1, root2), "vertex": vertex}
29
+ if delta > 0:
30
+ x1 = (-b + delta**0.5) / (2*a)
31
+ x2 = (-b - delta**0.5) / (2*a)
32
+ try:
33
+ x1_frac = Fraction(x1).limit_denominator()
34
+ x2_frac = Fraction(x2).limit_denominator()
35
+ return f"Two distinct real roots: x1 = {x1_frac}, x2 = {x2_frac}\nVertex at: {vertex}"
36
+ except:
37
+ return f"Two distinct real roots: x1 = {x1}, x2 = {x2}\nVertex at: {vertex}"
38
+ elif delta == 0:
39
+ x1 = -b / (2*a)
40
+ try:
41
+ x1_frac = Fraction(x1).limit_denominator()
42
+ return f"One real root (repeated): x = {x1_frac}\nVertex at: {vertex}"
43
+ except:
44
+ return f"One real root (repeated): x = {x1}\nVertex at: {vertex}"
45
+ else:
46
+ real_part = -b / (2*a)
47
+ imag_part = (-delta)**0.5 / (2*a)
48
+ return f"Two complex roots: x1 = {real_part} + {imag_part}i, x2 = {real_part} - {imag_part}i\nVertex at: {vertex}"
maths/arithmetic/add.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from typing import Union
3
+
4
+ def add(a: float, b: float) -> float:
5
+ """Add two numbers."""
6
+ try:
7
+ return float(a) + float(b)
8
+ except (ValueError, TypeError):
9
+ raise ValueError("Both inputs must be valid numbers")
maths/arithmetic/arithmetic.py DELETED
@@ -1,244 +0,0 @@
1
- """
2
- Enhanced arithmetic operations for elementary level with visualization capabilities.
3
- """
4
- import numpy as np
5
- import matplotlib.pyplot as plt
6
- from typing import Union, Tuple, Any
7
-
8
- def add(a: float, b: float) -> float:
9
- """Add two numbers."""
10
- try:
11
- return float(a) + float(b)
12
- except (ValueError, TypeError):
13
- raise ValueError("Both inputs must be valid numbers")
14
-
15
- def subtract(a: float, b: float) -> float:
16
- """Subtract b from a."""
17
- try:
18
- return float(a) - float(b)
19
- except (ValueError, TypeError):
20
- raise ValueError("Both inputs must be valid numbers")
21
-
22
- def multiply(a: float, b: float) -> float:
23
- """Multiply two numbers."""
24
- try:
25
- return float(a) * float(b)
26
- except (ValueError, TypeError):
27
- raise ValueError("Both inputs must be valid numbers")
28
-
29
- def divide(a: float, b: float) -> Union[float, str]:
30
- """Divide a by b."""
31
- try:
32
- a, b = float(a), float(b)
33
- if b == 0:
34
- return "Error: Division by zero"
35
- return a / b
36
- except (ValueError, TypeError):
37
- return "Error: Both inputs must be valid numbers"
38
-
39
- def create_number_line_visualization(numbers: list, operation: str, result: float) -> plt.Figure:
40
- """Create a number line visualization for arithmetic operations."""
41
- fig, ax = plt.subplots(figsize=(10, 4))
42
-
43
- # Determine range for number line
44
- all_nums = numbers + [result]
45
- min_val = min(all_nums) - 2
46
- max_val = max(all_nums) + 2
47
-
48
- # Draw number line
49
- ax.axhline(y=0, color='black', linewidth=2)
50
- ax.set_xlim(min_val, max_val)
51
- ax.set_ylim(-1, 1)
52
-
53
- # Add tick marks and labels
54
- tick_range = np.arange(int(min_val), int(max_val) + 1)
55
- ax.set_xticks(tick_range)
56
- for tick in tick_range:
57
- ax.axvline(x=tick, ymin=0.4, ymax=0.6, color='black', linewidth=1)
58
-
59
- # Highlight the numbers involved in the operation
60
- colors = ['red', 'blue', 'green']
61
- for i, num in enumerate(numbers):
62
- ax.plot(num, 0, 'o', markersize=10, color=colors[i % len(colors)],
63
- label=f'Number {i+1}: {num}')
64
-
65
- # Highlight the result
66
- ax.plot(result, 0, 's', markersize=12, color='purple', label=f'Result: {result}')
67
-
68
- # Add operation description
69
- if len(numbers) == 2:
70
- op_symbol = {'add': '+', 'subtract': '-', 'multiply': '×', 'divide': '÷'}.get(operation, '?')
71
- title = f"{numbers[0]} {op_symbol} {numbers[1]} = {result}"
72
- else:
73
- title = f"Result: {result}"
74
-
75
- ax.set_title(title, fontsize=14, fontweight='bold')
76
- ax.legend(loc='upper right')
77
- ax.set_ylabel('')
78
- ax.set_xlabel('Number Line')
79
- ax.grid(True, alpha=0.3)
80
-
81
- return fig
82
-
83
- def arithmetic_with_visualization(a: float, b: float, operation: str) -> Tuple[Any, plt.Figure]:
84
- """Perform arithmetic operation and return result with visualization."""
85
- try:
86
- a, b = float(a), float(b)
87
-
88
- if operation == 'add':
89
- result = add(a, b)
90
- elif operation == 'subtract':
91
- result = subtract(a, b)
92
- elif operation == 'multiply':
93
- result = multiply(a, b)
94
- elif operation == 'divide':
95
- result = divide(a, b)
96
- if isinstance(result, str): # Error case
97
- return result, None
98
- else:
99
- return "Error: Unknown operation", None
100
-
101
- # Create visualization
102
- fig = create_number_line_visualization([a, b], operation, result)
103
-
104
- return result, fig
105
-
106
- except Exception as e:
107
- return f"Error: {str(e)}", None
108
-
109
- def create_multiplication_table(number: int, max_multiplier: int = 12) -> plt.Figure:
110
- """Create a visual multiplication table."""
111
- fig, ax = plt.subplots(figsize=(8, 6))
112
-
113
- multipliers = np.arange(1, max_multiplier + 1)
114
- results = number * multipliers
115
-
116
- # Create bar chart
117
- bars = ax.bar(multipliers, results, color='skyblue', alpha=0.7, edgecolor='navy')
118
-
119
- # Add value labels on bars
120
- for bar, result in zip(bars, results):
121
- height = bar.get_height()
122
- ax.text(bar.get_x() + bar.get_width()/2., height + max(results) * 0.01,
123
- f'{result}', ha='center', va='bottom', fontweight='bold')
124
-
125
- ax.set_xlabel('Multiplier', fontsize=12)
126
- ax.set_ylabel('Result', fontsize=12)
127
- ax.set_title(f'Multiplication Table for {number}', fontsize=14, fontweight='bold')
128
- ax.grid(True, alpha=0.3)
129
- ax.set_xticks(multipliers)
130
-
131
- return fig
132
-
133
- def calculate_array(numbers: list, operations: list) -> float:
134
- """
135
- Perform a sequence of arithmetic operations on an array of numbers.
136
- Example: numbers=[2, 3, 4], operations=['add', 'multiply'] means (2 + 3) * 4
137
- Supported operations: 'add', 'subtract', 'multiply', 'divide'
138
- """
139
- if not numbers or not operations:
140
- raise ValueError("Both numbers and operations must be provided and non-empty.")
141
- if len(operations) != len(numbers) - 1:
142
- raise ValueError("Number of operations must be one less than number of numbers.")
143
-
144
- result = float(numbers[0])
145
- for i, op in enumerate(operations):
146
- num = float(numbers[i+1])
147
- if op == 'add':
148
- result = add(result, num)
149
- elif op == 'subtract':
150
- result = subtract(result, num)
151
- elif op == 'multiply':
152
- result = multiply(result, num)
153
- elif op == 'divide':
154
- result = divide(result, num)
155
- if isinstance(result, str): # Error case
156
- return result
157
- else:
158
- raise ValueError(f"Unsupported operation: {op}")
159
- return result
160
-
161
-
162
- def calculate_array_with_visualization(numbers: list, operations: list) -> tuple:
163
- """
164
- Perform a sequence of arithmetic operations on an array of numbers and return result with visualization.
165
- Visualization shows the step-by-step calculation on a number line.
166
- """
167
- if not numbers or not operations:
168
- return "Error: Both numbers and operations must be provided and non-empty.", None
169
- if len(operations) != len(numbers) - 1:
170
- return "Error: Number of operations must be one less than number of numbers.", None
171
-
172
- step_results = [float(numbers[0])]
173
- result = float(numbers[0])
174
- for i, op in enumerate(operations):
175
- num = float(numbers[i+1])
176
- if op == 'add':
177
- result = add(result, num)
178
- elif op == 'subtract':
179
- result = subtract(result, num)
180
- elif op == 'multiply':
181
- result = multiply(result, num)
182
- elif op == 'divide':
183
- result = divide(result, num)
184
- if isinstance(result, str): # Error case
185
- return result, None
186
- else:
187
- return f"Error: Unsupported operation: {op}", None
188
- step_results.append(result)
189
- # Visualization: show all intermediate results on the number line
190
- fig = create_number_line_visualization(numbers, ' -> '.join(operations), result)
191
- return result, fig
192
-
193
-
194
- def gcd(a: int, b: int) -> int:
195
- """Compute the greatest common divisor of two integers.
196
-
197
- Args:
198
- a: The first integer.
199
- b: The second integer.
200
-
201
- Returns:
202
- The greatest common divisor of a and b.
203
- """
204
- while b:
205
- a, b = b, a % b
206
- return abs(a)
207
-
208
-
209
- def lcm(a: int, b: int) -> int:
210
- """Compute the least common multiple of two integers.
211
-
212
- Args:
213
- a: The first integer.
214
- b: The second integer.
215
-
216
- Returns:
217
- The least common multiple of a and b.
218
- """
219
- if a == 0 or b == 0:
220
- return 0
221
- return abs(a * b) // gcd(a, b)
222
-
223
-
224
- def is_prime(n: int) -> bool:
225
- """Check if a number is a prime number.
226
-
227
- Args:
228
- n: The number to check.
229
-
230
- Returns:
231
- True if n is prime, False otherwise.
232
- """
233
- if n <= 1:
234
- return False
235
- if n <= 3:
236
- return True
237
- if n % 2 == 0 or n % 3 == 0:
238
- return False
239
- i = 5
240
- while i * i <= n:
241
- if n % i == 0 or n % (i + 2) == 0:
242
- return False
243
- i += 6
244
- return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
maths/arithmetic/arithmetic_interface.py CHANGED
@@ -1,5 +1,13 @@
1
  import gradio as gr
2
- from maths.arithmetic.arithmetic import add, subtract, multiply, divide, calculate_array, calculate_array_with_visualization, gcd, lcm, is_prime
 
 
 
 
 
 
 
 
3
 
4
  # Elementary Math Tab
5
  add_interface = gr.Interface(
 
1
  import gradio as gr
2
+ from .add import add
3
+ from .subtract import subtract
4
+ from .multiply import multiply
5
+ from .divide import divide
6
+ from .calculate_array import calculate_array
7
+ from .calculate_array_with_visualization import calculate_array_with_visualization
8
+ from .gcd import gcd
9
+ from .lcm import lcm
10
+ from .is_prime import is_prime
11
 
12
  # Elementary Math Tab
13
  add_interface = gr.Interface(
maths/arithmetic/arithmetic_with_visualization.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ from typing import Any, Tuple
3
+ from .add import add
4
+ from .subtract import subtract
5
+ from .multiply import multiply
6
+ from .divide import divide
7
+ from .number_line_visualization import create_number_line_visualization
8
+
9
+ def arithmetic_with_visualization(a: float, b: float, operation: str) -> Tuple[Any, plt.Figure]:
10
+ """Perform arithmetic operation and return result with visualization."""
11
+ try:
12
+ a, b = float(a), float(b)
13
+ if operation == 'add':
14
+ result = add(a, b)
15
+ elif operation == 'subtract':
16
+ result = subtract(a, b)
17
+ elif operation == 'multiply':
18
+ result = multiply(a, b)
19
+ elif operation == 'divide':
20
+ result = divide(a, b)
21
+ if isinstance(result, str):
22
+ return result, None
23
+ else:
24
+ return "Error: Unknown operation", None
25
+ fig = create_number_line_visualization([a, b], operation, result)
26
+ return result, fig
27
+ except Exception as e:
28
+ return f"Error: {str(e)}", None
maths/arithmetic/calculate_array.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .add import add
2
+ from .subtract import subtract
3
+ from .multiply import multiply
4
+ from .divide import divide
5
+
6
+ def calculate_array(numbers: list, operations: list) -> float:
7
+ """
8
+ Perform a sequence of arithmetic operations on an array of numbers.
9
+ Example: numbers=[2, 3, 4], operations=['add', 'multiply'] means (2 + 3) * 4
10
+ Supported operations: 'add', 'subtract', 'multiply', 'divide'
11
+ """
12
+ if not numbers or not operations:
13
+ raise ValueError("Both numbers and operations must be provided and non-empty.")
14
+ if len(operations) != len(numbers) - 1:
15
+ raise ValueError("Number of operations must be one less than number of numbers.")
16
+ result = float(numbers[0])
17
+ for i, op in enumerate(operations):
18
+ num = float(numbers[i+1])
19
+ if op == 'add':
20
+ result = add(result, num)
21
+ elif op == 'subtract':
22
+ result = subtract(result, num)
23
+ elif op == 'multiply':
24
+ result = multiply(result, num)
25
+ elif op == 'divide':
26
+ result = divide(result, num)
27
+ if isinstance(result, str):
28
+ return result
29
+ else:
30
+ raise ValueError(f"Unsupported operation: {op}")
31
+ return result
maths/arithmetic/calculate_array_with_visualization.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ from .add import add
3
+ from .subtract import subtract
4
+ from .multiply import multiply
5
+ from .divide import divide
6
+ from .number_line_visualization import create_number_line_visualization
7
+
8
+ def calculate_array_with_visualization(numbers: list, operations: list) -> tuple:
9
+ """
10
+ Perform a sequence of arithmetic operations on an array of numbers and return result with visualization.
11
+ Visualization shows the step-by-step calculation on a number line.
12
+ """
13
+ if not numbers or not operations:
14
+ return "Error: Both numbers and operations must be provided and non-empty.", None
15
+ if len(operations) != len(numbers) - 1:
16
+ return "Error: Number of operations must be one less than number of numbers.", None
17
+ step_results = [float(numbers[0])]
18
+ result = float(numbers[0])
19
+ for i, op in enumerate(operations):
20
+ num = float(numbers[i+1])
21
+ if op == 'add':
22
+ result = add(result, num)
23
+ elif op == 'subtract':
24
+ result = subtract(result, num)
25
+ elif op == 'multiply':
26
+ result = multiply(result, num)
27
+ elif op == 'divide':
28
+ result = divide(result, num)
29
+ if isinstance(result, str):
30
+ return result, None
31
+ else:
32
+ return f"Error: Unsupported operation: {op}", None
33
+ step_results.append(result)
34
+ fig = create_number_line_visualization(numbers, ' -> '.join(operations), result)
35
+ return result, fig
maths/arithmetic/divide.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Union
2
+
3
+ def divide(a: float, b: float) -> Union[float, str]:
4
+ """Divide a by b."""
5
+ try:
6
+ a, b = float(a), float(b)
7
+ if b == 0:
8
+ return "Error: Division by zero"
9
+ return a / b
10
+ except (ValueError, TypeError):
11
+ return "Error: Both inputs must be valid numbers"
maths/arithmetic/gcd.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ def gcd(a: int, b: int) -> int:
2
+ """Compute the greatest common divisor of two integers."""
3
+ while b:
4
+ a, b = b, a % b
5
+ return abs(a)
maths/arithmetic/is_prime.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def is_prime(n: int) -> bool:
2
+ """Check if a number is a prime number."""
3
+ if n <= 1:
4
+ return False
5
+ if n <= 3:
6
+ return True
7
+ if n % 2 == 0 or n % 3 == 0:
8
+ return False
9
+ i = 5
10
+ while i * i <= n:
11
+ if n % i == 0 or n % (i + 2) == 0:
12
+ return False
13
+ i += 6
14
+ return True
maths/arithmetic/lcm.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from .gcd import gcd
2
+
3
+ def lcm(a: int, b: int) -> int:
4
+ """Compute the least common multiple of two integers."""
5
+ if a == 0 or b == 0:
6
+ return 0
7
+ return abs(a * b) // gcd(a, b)
maths/arithmetic/multiplication_table.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+
4
+ def create_multiplication_table(number: int, max_multiplier: int = 12) -> plt.Figure:
5
+ """Create a visual multiplication table."""
6
+ fig, ax = plt.subplots(figsize=(8, 6))
7
+ multipliers = np.arange(1, max_multiplier + 1)
8
+ results = number * multipliers
9
+ bars = ax.bar(multipliers, results, color='skyblue', alpha=0.7, edgecolor='navy')
10
+ for bar, result in zip(bars, results):
11
+ height = bar.get_height()
12
+ ax.text(bar.get_x() + bar.get_width()/2., height + max(results) * 0.01,
13
+ f'{result}', ha='center', va='bottom', fontweight='bold')
14
+ ax.set_xlabel('Multiplier', fontsize=12)
15
+ ax.set_ylabel('Result', fontsize=12)
16
+ ax.set_title(f'Multiplication Table for {number}', fontsize=14, fontweight='bold')
17
+ ax.grid(True, alpha=0.3)
18
+ ax.set_xticks(multipliers)
19
+ return fig
maths/arithmetic/multiply.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from typing import Union
3
+
4
+ def multiply(a: float, b: float) -> float:
5
+ """Multiply two numbers."""
6
+ try:
7
+ return float(a) * float(b)
8
+ except (ValueError, TypeError):
9
+ raise ValueError("Both inputs must be valid numbers")
maths/arithmetic/number_line_visualization.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+
4
+ def create_number_line_visualization(numbers: list, operation: str, result: float) -> plt.Figure:
5
+ """Create a number line visualization for arithmetic operations."""
6
+ fig, ax = plt.subplots(figsize=(10, 4))
7
+ all_nums = numbers + [result]
8
+ min_val = min(all_nums) - 2
9
+ max_val = max(all_nums) + 2
10
+ ax.axhline(y=0, color='black', linewidth=2)
11
+ ax.set_xlim(min_val, max_val)
12
+ ax.set_ylim(-1, 1)
13
+ tick_range = np.arange(int(min_val), int(max_val) + 1)
14
+ ax.set_xticks(tick_range)
15
+ for tick in tick_range:
16
+ ax.axvline(x=tick, ymin=0.4, ymax=0.6, color='black', linewidth=1)
17
+ colors = ['red', 'blue', 'green']
18
+ for i, num in enumerate(numbers):
19
+ ax.plot(num, 0, 'o', markersize=10, color=colors[i % len(colors)],
20
+ label=f'Number {i+1}: {num}')
21
+ ax.plot(result, 0, 's', markersize=12, color='purple', label=f'Result: {result}')
22
+ if len(numbers) == 2:
23
+ op_symbol = {'add': '+', 'subtract': '-', 'multiply': '×', 'divide': '÷'}.get(operation, '?')
24
+ title = f"{numbers[0]} {op_symbol} {numbers[1]} = {result}"
25
+ else:
26
+ title = f"Result: {result}"
27
+ ax.set_title(title, fontsize=14, fontweight='bold')
28
+ ax.legend(loc='upper right')
29
+ ax.set_ylabel('')
30
+ ax.set_xlabel('Number Line')
31
+ ax.grid(True, alpha=0.3)
32
+ return fig
maths/arithmetic/subtract.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from typing import Union
3
+
4
+ def subtract(a: float, b: float) -> float:
5
+ """Subtract b from a."""
6
+ try:
7
+ return float(a) - float(b)
8
+ except (ValueError, TypeError):
9
+ raise ValueError("Both inputs must be valid numbers")