Spaces:
Runtime error
Runtime error
algebra & arithmetic modularized
Browse files- maths/algebra/algebra.py +0 -213
- maths/algebra/algebra_interface.py +5 -4
- maths/algebra/evaluate_expression.py +5 -0
- maths/algebra/polynomial_operations.py +64 -0
- maths/algebra/simplify_radical.py +24 -0
- maths/algebra/solve_linear_equation.py +9 -0
- maths/algebra/solve_quadratic.py +48 -0
- maths/arithmetic/add.py +9 -0
- maths/arithmetic/arithmetic.py +0 -244
- maths/arithmetic/arithmetic_interface.py +9 -1
- maths/arithmetic/arithmetic_with_visualization.py +28 -0
- maths/arithmetic/calculate_array.py +31 -0
- maths/arithmetic/calculate_array_with_visualization.py +35 -0
- maths/arithmetic/divide.py +11 -0
- maths/arithmetic/gcd.py +5 -0
- maths/arithmetic/is_prime.py +14 -0
- maths/arithmetic/lcm.py +7 -0
- maths/arithmetic/multiplication_table.py +19 -0
- maths/arithmetic/multiply.py +9 -0
- maths/arithmetic/number_line_visualization.py +32 -0
- maths/arithmetic/subtract.py +9 -0
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.
|
3 |
-
|
4 |
-
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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")
|