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")
|