mathgenerator.algebra

  1from ._latexBuilder import bmatrix
  2import random
  3import math
  4import fractions
  5import sympy
  6
  7
  8def basic_algebra(max_variable=10):
  9    r"""Basic Algebra
 10
 11    | Ex. Problem | Ex. Solution |
 12    | --- | --- |
 13    | $1x + 5 = 5$ | $0$ |
 14    """
 15    a = random.randint(1, max_variable)
 16    b = random.randint(1, max_variable)
 17    c = random.randint(b, max_variable)
 18
 19    # calculate gcd
 20    def calculate_gcd(x, y):
 21        while (y):
 22            x, y = y, x % y
 23        return x
 24
 25    i = calculate_gcd((c - b), a)
 26    x = f"{(c - b)//i}/{a//i}"
 27
 28    if (c - b == 0):
 29        x = "0"
 30    elif a == 1 or a == i:
 31        x = f"{c - b}"
 32
 33    problem = f"${a}x + {b} = {c}$"
 34    solution = f"${x}$"
 35    return problem, solution
 36
 37
 38def combine_like_terms(max_coef=10, max_exp=20, max_terms=10):
 39    r"""Combine Like Terms
 40
 41    | Ex. Problem | Ex. Solution |
 42    | --- | --- |
 43    | $6x^{9} + 3x^{2} + 5x^{19} + 3x^{17}$ | $3x^{2} + 6x^{9} + 3x^{17} + 5x^{19}$ |
 44    """
 45    numTerms = random.randint(1, max_terms)
 46
 47    coefs = [random.randint(1, max_coef) for _ in range(numTerms)]
 48    exponents = [random.randint(1, max(max_exp - 1, 2))
 49                 for _ in range(numTerms)]
 50
 51    problem = " + ".join([f"{coefs[i]}x^{{{exponents[i]}}}" for i in range(numTerms)])
 52    d = {}
 53    for i in range(numTerms):
 54        if exponents[i] in d:
 55            d[exponents[i]] += coefs[i]
 56        else:
 57            d[exponents[i]] = coefs[i]
 58    solution = " + ".join([f"{d[k]}x^{{{k}}}" for k in sorted(d)])
 59
 60    return f'${problem}$', f'${solution}$'
 61
 62
 63def complex_quadratic(prob_type=0, max_range=10):
 64    r"""Complex Quadratic Equation
 65
 66    | Ex. Problem | Ex. Solution |
 67    | --- | --- |
 68    | Find the roots of given Quadratic Equation $x^2 + 8x + 8 = 0$ | $((-1.172, -6.828)) = (\frac{-8 + \sqrt{32}}{2}, (\frac{-8 - \sqrt{32}}{2})$ |
 69    """
 70    if prob_type < 0 or prob_type > 1:
 71        print("prob_type not supported")
 72        print("prob_type = 0 for real roots problems ")
 73        print("prob_tpye = 1 for imaginary roots problems")
 74        return None
 75    if prob_type == 0:
 76        d = -1
 77        while d < 0:
 78            a = random.randrange(1, max_range)
 79            b = random.randrange(1, max_range)
 80            c = random.randrange(1, max_range)
 81
 82            d = (b**2 - 4 * a * c)
 83    else:
 84        d = 0
 85        while d >= 0:
 86            a = random.randrange(1, max_range)
 87            b = random.randrange(1, max_range)
 88            c = random.randrange(1, max_range)
 89
 90            d = (b**2 - 4 * a * c)
 91
 92    eq = ''
 93
 94    if a == 1:
 95        eq += 'x^2 + '
 96    else:
 97        eq += str(a) + 'x^2 + '
 98
 99    if b == 1:
100        eq += 'x + '
101    else:
102        eq += str(b) + 'x + '
103
104    eq += str(c) + ' = 0'
105
106    problem = f'Find the roots of given Quadratic Equation ${eq}$'
107
108    if d < 0:
109        sqrt_d = (-d)**0.5
110
111        if sqrt_d - int(sqrt_d) == 0:
112            sqrt_d = int(sqrt_d)
113            solution = rf'(\frac{{{-b} + {sqrt_d}i}}{{{2*a}}}, \frac{{{-b} - {sqrt_d}i}}{{{2*a}}})'
114        else:
115            solution = rf'(\frac{{{-b} + \sqrt{{{-d}}}i}}{{{2*a}}}, \frac{{{-b} - \sqrt{{{-d}}}i}}{{{2*a}}})'
116
117        return problem, solution
118
119    else:
120        s_root1 = round((-b + (d)**0.5) / (2 * a), 3)
121        s_root2 = round((-b - (d)**0.5) / (2 * a), 3)
122
123        sqrt_d = (d)**0.5
124
125        if sqrt_d - int(sqrt_d) == 0:
126            sqrt_d = int(sqrt_d)
127            g_sol = rf'(\frac{{{-b} + {sqrt_d}}}{{{2*a}}}, \frac{{{-b} - {sqrt_d}}}{{{2*a}}})'
128        else:
129            g_sol = rf'(\frac{{{-b} + \sqrt{{{d}}}}}{{{2*a}}}, (\frac{{{-b} - \sqrt{{{d}}}}}{{{2*a}}})'
130
131        solution = f'$({s_root1, s_root2}) = {g_sol}$'
132
133        return problem, solution
134
135
136def compound_interest(max_principle=10000,
137                      max_rate=10,
138                      max_time=10):
139    r"""Compound Interest
140
141    | Ex. Problem | Ex. Solution |
142    | --- | --- |
143    | Compound interest for a principle amount of $2679$ dollars, $9$% rate of interest and for a time period of $3$ years is $=$ | $3469.38$ |
144    """
145    p = random.randint(1000, max_principle)
146    r = random.randint(1, max_rate)
147    n = random.randint(1, max_time)
148    a = round(p * (1 + r / 100)**n, 2)
149
150    problem = f"Compound interest for a principle amount of ${p}$ dollars, ${r}$% rate of interest and for a time period of ${n}$ years is $=$"
151    return problem, f'${a}$'
152
153
154def distance_two_points(max_val_xy=20, min_val_xy=-20):
155    r"""Distance between 2 points
156
157    | Ex. Problem | Ex. Solution |
158    | --- | --- |
159    | Find the distance between $(-19, -6)$ and $(15, -16)$ | $\sqrt{1256}$ |
160    """
161    point1X = random.randint(min_val_xy, max_val_xy + 1)
162    point1Y = random.randint(min_val_xy, max_val_xy + 1)
163    point2X = random.randint(min_val_xy, max_val_xy + 1)
164    point2Y = random.randint(min_val_xy, max_val_xy + 1)
165
166    distanceSq = (point1X - point2X) ** 2 + (point1Y - point2Y) ** 2
167
168    solution = rf"$\sqrt{{{distanceSq}}}$"
169    problem = f"Find the distance between $({point1X}, {point1Y})$ and $({point2X}, {point2Y})$"
170    return problem, solution
171
172
173def expanding(range_x1=10,
174              range_x2=10,
175              range_a=10,
176              range_b=10):
177    r"""Expanding Factored Binomial
178
179    | Ex. Problem | Ex. Solution |
180    | --- | --- |
181    |$(x-6)(-3x-3)$ | $x^2+18x+18$ |
182    """
183    x1 = random.randint(-range_x1, range_x1)
184    x2 = random.randint(-range_x2, range_x2)
185    a = random.randint(-range_a, range_a)
186    b = random.randint(-range_b, range_b)
187
188    def intParser(z):
189        if (z > 0):
190            return f"+{z}"
191        elif (z < 0):
192            return f"-{abs(z)}"
193        else:
194            return ""
195
196    c1 = intParser(a * b)
197    c2 = intParser((a * x2) + (b * x1))
198    c3 = intParser(x1 * x2)
199
200    p1 = intParser(a)
201    p2 = intParser(x1)
202    p3 = intParser(b)
203    p4 = intParser(x2)
204
205    if p1 == "+1":
206        p1 = ""
207    elif len(p1) > 0 and p1[0] == "+":
208        p1 = p1[1:]
209    if p3 == "+1":
210        p3 = ""
211    elif p3[0] == "+":
212        p3 = p3[1:]
213
214    if c1 == "+1":
215        c1 = ""
216    elif len(c1) > 0 and c1[0] == "+":
217        c1 = c1[1:]  # Cuts off the plus for readability
218    if c2 == "+1":
219        c2 = ""
220
221    problem = f"$({p1}x{p2})({p3}x{p4})$"
222    solution = f"${c1}x^2{c2}x{c3}$"
223    return problem, solution
224
225
226def factoring(range_x1=10, range_x2=10):
227    r"""Factoring Quadratic
228    Given a quadratic equation in the form x^2 + bx + c, factor it into it's roots (x - x1)(x -x2)
229
230    | Ex. Problem | Ex. Solution |
231    | --- | --- |
232    | $x^2+2x-24$ | $(x-4)(x+6)$ |
233    """
234    x1 = random.randint(-range_x1, range_x1)
235    x2 = random.randint(-range_x2, range_x2)
236
237    def intParser(z):
238        if (z > 0):
239            return f"+{z}"
240        elif (z < 0):
241            return f"-{abs(z)}"
242        else:
243            return ""
244
245    b = intParser(x1 + x2)
246    c = intParser(x1 * x2)
247
248    if b == "+1":
249        b = "+"
250    if b == "":
251        problem = f"x^2{c}"
252    else:
253        problem = f"x^2{b}x{c}"
254
255    x1 = intParser(x1)
256    x2 = intParser(x2)
257    solution = f"$(x{x1})(x{x2})$"
258    return f"${problem}$", solution
259
260
261def int_matrix_22_determinant(max_matrix_val=100):
262    r"""Determinant to 2x2 Matrix
263
264    | Ex. Problem | Ex. Solution |
265    | --- | --- |
266    | $\det \begin{bmatrix} 88 & 40 \\\ 9 & 91 \end{bmatrix}= $ | $7648$ |
267    """
268    a = random.randint(0, max_matrix_val)
269    b = random.randint(0, max_matrix_val)
270    c = random.randint(0, max_matrix_val)
271    d = random.randint(0, max_matrix_val)
272
273    determinant = a * d - b * c
274    lst = [[a, b], [c, d]]
275
276    problem = rf"$\det {bmatrix(lst)}= $"
277    solution = f"${determinant}$"
278    return problem, solution
279
280
281def intersection_of_two_lines(min_m=-10,
282                              max_m=10,
283                              min_b=-10,
284                              max_b=10,
285                              min_denominator=1,
286                              max_denominator=6):
287    r"""Intersection of two lines
288
289    | Ex. Problem | Ex. Solution |
290    | --- | --- |
291    | Find the point of intersection of the two lines: $y = \frac{-2}{6}x + 3$ and $y = \frac{3}{6}x - 8$ | $(\frac{66}{5}, \frac{-7}{5})$ |
292    """
293    def generateEquationString(m, b):
294        """
295        Generates an equation given the slope and intercept.
296        It handles cases where m is fractional.
297        It also ensures that we don't have weird signs such as y = mx + -b.
298        """
299        if m[0] == 0:
300            m = 0
301        elif abs(m[0]) == abs(m[1]):
302            m = m[0] // m[1]
303        elif m[1] == 1:
304            m = m[0]
305        else:
306            m = rf"\frac{{{m[0]}}}{{{m[1]}}}"
307        base = "y ="
308        if m != 0:
309            if m == 1:
310                base = f"{base} x"
311            elif m == -1:
312                base = f"{base} -x"
313            else:
314                base = f"{base} {m}x"
315        if b > 0:
316            if m == 0:
317                return f"{base} {b}"
318            else:
319                return f"{base} + {b}"
320        elif b < 0:
321            if m == 0:
322                return f"{base} -{b * -1}"
323            else:
324                return f"{base} - {b * -1}"
325        else:
326            if m == 0:
327                return f"{base} 0"
328            else:
329                return base
330
331    def fractionToString(x):
332        """
333        Converts the given fractions.Fraction into a string.
334        """
335        if x.denominator == 1:
336            x = x.numerator
337        else:
338            x = rf"\frac{{{x.numerator}}}{{{x.denominator}}}"
339        return x
340
341    m1 = (random.randint(min_m,
342                         max_m), random.randint(min_denominator, max_denominator))
343    m2 = (random.randint(min_m,
344                         max_m), random.randint(min_denominator, max_denominator))
345
346    b1 = random.randint(min_b, max_b)
347    b2 = random.randint(min_b, max_b)
348
349    eq1 = generateEquationString(m1, b1)
350    eq2 = generateEquationString(m2, b2)
351
352    problem = f"Find the point of intersection of the two lines: ${eq1}$ and ${eq2}$"
353
354    m1 = fractions.Fraction(*m1)
355    m2 = fractions.Fraction(*m2)
356    # if m1 == m2 then the slopes are equal
357    # This can happen if both line are the same
358    # Or if they are parallel
359    # In either case there is no intersection
360
361    if m1 == m2:
362        solution = "No Solution"
363    else:
364        intersection_x = (b1 - b2) / (m2 - m1)
365        intersection_y = ((m2 * b1) - (m1 * b2)) / (m2 - m1)
366        solution = f"$({fractionToString(intersection_x)}, {fractionToString(intersection_y)})$"
367
368    return problem, solution
369
370
371def invert_matrix(square_matrix_dimension=3,
372                  max_matrix_element=99,
373                  only_integer_elements_in_inverted_matrixe=True):
374    r"""Invert Matrix
375
376    | Ex. Problem | Ex. Solution |
377    | --- | --- |
378    | Inverse of Matrix $\begin{bmatrix} 4 & 1 & 4 \\\ 5 & 1 & 5 \\\ 12 & 3 & 13 \end{bmatrix}$ is: | $\begin{bmatrix} 2 & 1 & -1 \\\ 5 & -4 & 0 \\\ -3 & 0 & 1 \end{bmatrix}$ |
379    """
380    if only_integer_elements_in_inverted_matrixe is True:
381        isItOk = False
382        Mat = list()
383        while (isItOk is False):
384            Mat = list()
385            for i in range(0, square_matrix_dimension):
386                z = list()
387                for j in range(0, square_matrix_dimension):
388                    z.append(0)
389                z[i] = 1
390                Mat.append(z)
391            MaxAllowedMatrixElement = math.ceil(
392                pow(max_matrix_element, 1 / (square_matrix_dimension)))
393            randomlist = random.sample(range(0, MaxAllowedMatrixElement + 1),
394                                       square_matrix_dimension)
395
396            for i in range(0, square_matrix_dimension):
397                if i == square_matrix_dimension - 1:
398                    Mat[0] = [
399                        j + (k * randomlist[i])
400                        for j, k in zip(Mat[0], Mat[i])
401                    ]
402                else:
403                    Mat[i + 1] = [
404                        j + (k * randomlist[i])
405                        for j, k in zip(Mat[i + 1], Mat[i])
406                    ]
407
408            for i in range(1, square_matrix_dimension - 1):
409                Mat[i] = [
410                    sum(i) for i in zip(Mat[square_matrix_dimension - 1], Mat[i])
411                ]
412
413            isItOk = True
414            for i in Mat:
415                for j in i:
416                    if j > max_matrix_element:
417                        isItOk = False
418                        break
419                if isItOk is False:
420                    break
421
422        random.shuffle(Mat)
423        Mat = sympy.Matrix(Mat)
424        Mat = sympy.Matrix.transpose(Mat)
425        Mat = Mat.tolist()
426        random.shuffle(Mat)
427        Mat = sympy.Matrix(Mat)
428        Mat = sympy.Matrix.transpose(Mat)
429
430    else:
431        randomlist = list(sympy.primerange(0, max_matrix_element + 1))
432        plist = random.sample(randomlist, square_matrix_dimension)
433        randomlist = random.sample(
434            range(0, max_matrix_element + 1),
435            square_matrix_dimension * square_matrix_dimension)
436        randomlist = list(set(randomlist) - set(plist))
437        n_list = random.sample(
438            randomlist, square_matrix_dimension * (square_matrix_dimension - 1))
439        Mat = list()
440        for i in range(0, square_matrix_dimension):
441            z = list()
442            z.append(plist[i])
443            for j in range(0, square_matrix_dimension - 1):
444                z.append(n_list[(i * square_matrix_dimension) + j - i])
445            random.shuffle(z)
446            Mat.append(z)
447        Mat = sympy.Matrix(Mat)
448
449    problem = 'Inverse of Matrix $' + bmatrix(Mat.tolist()) + '$ is:'
450    solution = f'${bmatrix(sympy.Matrix.inv(Mat).tolist())}$'
451    return problem, solution
452
453
454def linear_equations(n=2, var_range=20, coeff_range=20):
455    r"""Linear Equations
456
457    | Ex. Problem | Ex. Solution |
458    | --- | --- |
459    | Given the equations $10x + -20y = 310$ and $-16x + -17y = 141$, solve for $x$ and $y$ | $x = 5$, $y = -13$ |
460    """
461    if n > 10:
462        print("[!] n cannot be greater than 10")
463        return None, None
464
465    vars = ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g'][:n]
466    soln = [random.randint(-var_range, var_range) for i in range(n)]
467    problem = list()
468    solution = "$, $".join(
469        ["{} = {}".format(vars[i], soln[i]) for i in range(n)])
470
471    for _ in range(n):
472        coeff = [random.randint(-coeff_range, coeff_range) for i in range(n)]
473        res = sum([coeff[i] * soln[i] for i in range(n)])
474        prob = [
475            "{}{}".format(coeff[i], vars[i]) if coeff[i] != 0 else ""
476            for i in range(n)
477        ]
478
479        while "" in prob:
480            prob.remove("")
481        prob = " + ".join(prob) + " = " + str(res)
482        problem.append(prob)
483
484    # problem = "\n".join(problem)
485    problem = "$ and $".join(problem)
486
487    return f'Given the equations ${problem}$, solve for $x$ and $y$', f'${solution}$'
488
489
490def line_equation_from_2_points(max_val=20):
491    r"""Equation of Line from Two Points
492
493    | Ex. Problem | Ex. Solution |
494    | --- | --- |
495    | Find the equation of the line passing through the points $(-19,-8)$ and $(-2,0)$. | $y=\frac{8}{17}x+\frac{16}{17}$ |
496    """
497    x1 = random.randint(-max_val, max_val)
498    x2 = random.randint(-max_val, max_val)
499    if x1 == x2:
500        return line_equation_from_2_points(max_val=max_val)
501    y1 = random.randint(-max_val, max_val)
502    y2 = random.randint(-max_val, max_val)
503    m1 = (y2 - y1) // math.gcd(y2 - y1, x2 - x1)
504    m2 = (x2 - x1) // math.gcd(y2 - y1, x2 - x1)
505    c1 = (y1 * (x2 - x1) - (y2 - y1) * x1) // math.gcd(y1 * (x2 - x1) - (y2 - y1) * x1, (x2 - x1))
506    c2 = (x2 - x1) // math.gcd(y1 * (x2 - x1) - (y2 - y1) * x1, (x2 - x1))
507    c = rf"{'+' if c1 >= 0 else '-'}\frac{{{abs(c1)}}}{{{c2}}}" if c1 != 0 else ""
508    if c2 < 0:
509        c2 = -c2
510        c1 = -c1
511        c = rf"{'+' if c1 >= 0 else '-'}\frac{{{abs(c1)}}}{{{c2}}}"
512    if c2 == 1:
513        c = f"{c1:+}"
514
515    problem = f'Find the equation of the line passing through the points $({x1},{y1})$ and $({x2},{y2})$.'
516
517    if m1 == 0:
518        return problem, f"$y={c}$"
519    if m2 < 0:
520        m1 = -m1
521        m2 = -m2
522    if m2 == 1:
523        if m1 == 1:
524            return problem, f"$y=x{c}$"
525        if m1 == -1:
526            return problem, f"$y=-x{c}$"
527        return problem, f"y={m1}x{c}"
528
529    return problem, rf"$y=\frac{{{m1}}}{{{m2}}}x{c}$"
530
531
532def log(max_base=3, max_val=8):
533    r"""Logarithm
534
535    | Ex. Problem | Ex. Solution |
536    | --- | --- |
537    | $log_{3}(243)=$ | $5$ |
538    """
539    a = random.randint(1, max_val)
540    b = random.randint(2, max_base)
541    c = pow(b, a)
542
543    problem = f'$log_{{{b}}}({c})=$'
544    solution = f'${a}$'
545    return problem, solution
546
547
548def matrix_multiplication(max_val=100, max_dim=10):
549    r"""Multiply Two Matrices
550
551    | Ex. Problem | Ex. Solution |
552    | --- | --- |
553    | Multiply $\begin{bmatrix} 15 & 72 \\\ 64 & -20 \\\ 18 & 59 \\\ -21 & -55 \\\ 20 & -12 \\\ -75 & -42 \\\ 47 & 89 \\\ -53 & 27 \\\ -56 & 44 \end{bmatrix}$ and $\begin{bmatrix} 49 & -2 & 68 & -28 \\\ 49 & 6 & 83 & 42 \end{bmatrix}$ | $\begin{bmatrix} 4263 & 402 & 6996 & 2604 \\\ 2156 & -248 & 2692 & -2632 \\\ 3773 & 318 & 6121 & 1974 \\\ -3724 & -288 & -5993 & -1722 \\\ 392 & -112 & 364 & -1064 \\\ -5733 & -102 & -8586 & 336 \\\ 6664 & 440 & 10583 & 2422 \\\ -1274 & 268 & -1363 & 2618 \\\ -588 & 376 & -156 & 3416 \end{bmatrix}$ |
554    """
555    m = random.randint(2, max_dim)
556    n = random.randint(2, max_dim)
557    k = random.randint(2, max_dim)
558
559    # generate matrices a and b
560    a = [[random.randint(-max_val, max_val) for _ in range(n)]
561         for _ in range(m)]
562    b = [[random.randint(-max_val, max_val) for _ in range(k)]
563         for _ in range(n)]
564
565    res = []
566    for r in range(m):
567        res.append([])
568        for c in range(k):
569            temp = 0
570            for t in range(n):
571                temp += a[r][t] * b[t][c]
572            res[r].append(temp)
573
574    problem = f"Multiply ${bmatrix(a)}$ and ${bmatrix(b)}$"
575    solution = f'${bmatrix(res)}$'
576    return problem, solution
577
578
579def midpoint_of_two_points(max_value=20):
580    r"""Midpoint of two points
581
582    | Ex. Problem | Ex. Solution |
583    | --- | --- |
584    | The midpoint of $(-8,10)$ and $(18,0) = $ | $(5.0,5.0)$ |
585    """
586    x1 = random.randint(-20, max_value)
587    y1 = random.randint(-20, max_value)
588    x2 = random.randint(-20, max_value)
589    y2 = random.randint(-20, max_value)
590    xm = (x1 + x2) / 2
591    ym = (y1 + y2) / 2
592
593    problem = f"The midpoint of $({x1},{y1})$ and $({x2},{y2}) = $"
594    solution = f"$({xm},{ym})$"
595    return problem, solution
596
597
598def multiply_complex_numbers(min_real_imaginary_num=-20,
599                             max_real_imaginary_num=20):
600    r"""Multiplication of 2 complex numbers
601
602    | Ex. Problem | Ex. Solution |
603    | --- | --- |
604    | $(14+18j) * (14+15j) = $ | $(-74+462j)$ |
605    """
606    num1 = complex(random.randint(min_real_imaginary_num, max_real_imaginary_num),
607                   random.randint(min_real_imaginary_num, max_real_imaginary_num))
608    num2 = complex(random.randint(min_real_imaginary_num, max_real_imaginary_num),
609                   random.randint(min_real_imaginary_num, max_real_imaginary_num))
610    product = num1 * num2
611
612    problem = f"${num1} * {num2} = $"
613    solution = f'${product}$'
614    return problem, solution
615
616
617def multiply_int_to_22_matrix(max_matrix_val=10, max_res=100):
618    r"""Multiply Integer to 2x2 Matrix
619
620    | Ex. Problem | Ex. Solution |
621    | --- | --- |
622    | $5 * \begin{bmatrix} 1 & 0 \\\ 2 & 9 \end{bmatrix} =$ | $\begin{bmatrix} 5 & 0 \\\ 10 & 45 \end{bmatrix}$ |
623    """
624    a = random.randint(0, max_matrix_val)
625    b = random.randint(0, max_matrix_val)
626    c = random.randint(0, max_matrix_val)
627    d = random.randint(0, max_matrix_val)
628
629    constant = random.randint(0, int(max_res / max(a, b, c, d)))
630
631    a1 = a * constant
632    b1 = b * constant
633    c1 = c * constant
634    d1 = d * constant
635    lst = [[a, b], [c, d]]
636    lst1 = [[a1, b1], [c1, d1]]
637
638    problem = f'${constant} * {bmatrix(lst)} =$'
639    solution = f'${bmatrix(lst1)}$'
640    return problem, solution
641
642
643def quadratic_equation(max_val=100):
644    r"""Quadratic Equation
645
646    | Ex. Problem | Ex. Solution |
647    | --- | --- |
648    | What are the zeros of the quadratic equation $22x^2+137x+25=0$ | ${-0.19, -6.04}$ |
649    """
650    a = random.randint(1, max_val)
651    c = random.randint(1, max_val)
652    b = random.randint(
653        round(math.sqrt(4 * a * c)) + 1, round(math.sqrt(4 * max_val * max_val)))
654    D = math.sqrt(b * b - 4 * a * c)
655    res = {round((-b + D) / (2 * a), 2), round((-b - D) / (2 * a), 2)}
656
657    problem = f"What are the zeros of the quadratic equation ${a}x^2+{b}x+{c}=0$"
658    solution = f'${res}$'
659    return problem, solution
660
661
662def simple_interest(max_principle=10000,
663                    max_rate=10,
664                    max_time=10):
665    r"""Simple Interest
666
667    | Ex. Problem | Ex. Solution |
668    | --- | --- |
669    | Simple interest for a principle amount of $7217$ dollars, $3$% rate of interest and for a time period of $10$ years is $=$ | $2165.1$ |
670    """
671    p = random.randint(1000, max_principle)
672    r = random.randint(1, max_rate)
673    t = random.randint(1, max_time)
674    s = round((p * r * t) / 100, 2)
675
676    problem = f"Simple interest for a principle amount of ${p}$ dollars, ${r}$% rate of interest and for a time period of ${t}$ years is $=$ "
677    solution = f'${s}$'
678    return problem, solution
679
680
681def system_of_equations(range_x=10,
682                        range_y=10,
683                        coeff_mult_range=10):
684    r"""Solve a System of Equations in R^2
685
686    | Ex. Problem | Ex. Solution |
687    | --- | --- |
688    | Given $-x + 5y = -28$ and $9x + 2y = 64$, solve for $x$ and $y$. | $x = 8$, $y = -4$ |
689    """
690    # Generate solution point first
691    x = random.randint(-range_x, range_x)
692    y = random.randint(-range_y, range_y)
693    # Start from reduced echelon form (coeffs 1)
694    c1 = [1, 0, x]
695    c2 = [0, 1, y]
696
697    def randNonZero():
698        return random.choice(
699            [i for i in range(-coeff_mult_range, coeff_mult_range) if i != 0])
700
701    # Add random (non-zero) multiple of equations (rows) to each other
702    c1_mult = randNonZero()
703    c2_mult = randNonZero()
704    new_c1 = [c1[i] + c1_mult * c2[i] for i in range(len(c1))]
705    new_c2 = [c2[i] + c2_mult * c1[i] for i in range(len(c2))]
706    # For extra randomness, now add random (non-zero) multiples of original rows
707    # to themselves
708    c1_mult = randNonZero()
709    c2_mult = randNonZero()
710    new_c1 = [new_c1[i] + c1_mult * c1[i] for i in range(len(c1))]
711    new_c2 = [new_c2[i] + c2_mult * c2[i] for i in range(len(c2))]
712
713    def coeffToFuncString(coeffs):
714        # lots of edge cases for perfect formatting!
715        x_sign = '-' if coeffs[0] < 0 else ''
716        # No redundant 1s
717        x_coeff = str(abs(coeffs[0])) if abs(coeffs[0]) != 1 else ''
718        # If x coeff is 0, dont include x
719        x_str = f'{x_sign}{x_coeff}x' if coeffs[0] != 0 else ''
720        # if x isn't included and y is positive, dont include operator
721        op = ' - ' if coeffs[1] < 0 else (' + ' if x_str != '' else '')
722        # No redundant 1s
723        y_coeff = abs(coeffs[1]) if abs(coeffs[1]) != 1 else ''
724        # Don't include if 0, unless x is also 0 (probably never happens)
725        y_str = f'{y_coeff}y' if coeffs[1] != 0 else (
726            '' if x_str != '' else '0')
727        return f'{x_str}{op}{y_str} = {coeffs[2]}'
728
729    problem = f"Given ${coeffToFuncString(new_c1)}$ and ${coeffToFuncString(new_c2)}$, solve for $x$ and $y$."
730    solution = f"$x = {x}$, $y = {y}$"
731    return problem, solution
732    # Add random (non-zero) multiple of equations to each other
733
734
735def vector_cross(min_val=-20, max_val=20):
736    r"""Cross product of 2 vectors
737
738    | Ex. Problem | Ex. Solution |
739    | --- | --- |
740    | $[-1, -4, 10] \times [-11, 1, -16] = $ | $[54, -126, -45]$ |
741    """
742    a = [random.randint(min_val, max_val) for _ in range(3)]
743    b = [random.randint(min_val, max_val) for _ in range(3)]
744    c = [
745        a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
746        a[0] * b[1] - a[1] * b[0]
747    ]
748
749    problem = rf"${a} \times {b} = $"
750    solution = f"${c}$"
751    return problem, solution
752
753
754def vector_dot(min_val=-20, max_val=20):
755    r"""Dot product of 2 vectors
756
757    | Ex. Problem | Ex. Solution |
758    | --- | --- |
759    | $[12, -9, -8]\cdot[-9, 8, 1]=$ | $-188$ |
760    """
761    a = [random.randint(min_val, max_val) for i in range(3)]
762    b = [random.randint(min_val, max_val) for i in range(3)]
763    c = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
764
765    problem = rf'${a}\cdot{b}=$'
766    solution = f'${c}$'
767    return problem, solution
768
769
770def orthogonal_projection(min_val=-10, max_val=10):
771    r"""Orthogonal Projection
772
773    | Ex. Problem | Ex. Solution |
774    | --- | --- |
775    | Find the orthogonal projection of $[2, 3]$ onto $[4, -7]$ | $[\frac{-4}{5}, \frac{7}{5}]$ |
776    """
777    v = [random.randint(min_val, max_val) for _ in range(2)]
778    u = [random.randint(min_val, max_val) for _ in range(2)]
779    dot_t = v[0] * u[0] + v[1] * u[1]
780    dot_b = u[0] * u[0] + u[1] * u[1]
781    frac = fractions.Fraction(dot_t, dot_b).limit_denominator()
782    y = [frac * u[0], frac * u[1]]
783
784    if y[0].denominator != 1:
785        y[0] = rf'\frac{{{y[0].numerator}}}{{{y[0].denominator}}}'
786    if y[1].denominator != 1:
787        y[1] = rf'\frac{{{y[1].numerator}}}{{{y[1].denominator}}}'
788
789    problem = f'Find the orthogonal projection of ${v}$ onto ${u}$'
790    solution = f'$[{y[0]}, {y[1]}]$'
791    return problem, solution
def basic_algebra(max_variable=10):
 9def basic_algebra(max_variable=10):
10    r"""Basic Algebra
11
12    | Ex. Problem | Ex. Solution |
13    | --- | --- |
14    | $1x + 5 = 5$ | $0$ |
15    """
16    a = random.randint(1, max_variable)
17    b = random.randint(1, max_variable)
18    c = random.randint(b, max_variable)
19
20    # calculate gcd
21    def calculate_gcd(x, y):
22        while (y):
23            x, y = y, x % y
24        return x
25
26    i = calculate_gcd((c - b), a)
27    x = f"{(c - b)//i}/{a//i}"
28
29    if (c - b == 0):
30        x = "0"
31    elif a == 1 or a == i:
32        x = f"{c - b}"
33
34    problem = f"${a}x + {b} = {c}$"
35    solution = f"${x}$"
36    return problem, solution

Basic Algebra

Ex. Problem Ex. Solution
$1x + 5 = 5$ $0$
def combine_like_terms(max_coef=10, max_exp=20, max_terms=10):
39def combine_like_terms(max_coef=10, max_exp=20, max_terms=10):
40    r"""Combine Like Terms
41
42    | Ex. Problem | Ex. Solution |
43    | --- | --- |
44    | $6x^{9} + 3x^{2} + 5x^{19} + 3x^{17}$ | $3x^{2} + 6x^{9} + 3x^{17} + 5x^{19}$ |
45    """
46    numTerms = random.randint(1, max_terms)
47
48    coefs = [random.randint(1, max_coef) for _ in range(numTerms)]
49    exponents = [random.randint(1, max(max_exp - 1, 2))
50                 for _ in range(numTerms)]
51
52    problem = " + ".join([f"{coefs[i]}x^{{{exponents[i]}}}" for i in range(numTerms)])
53    d = {}
54    for i in range(numTerms):
55        if exponents[i] in d:
56            d[exponents[i]] += coefs[i]
57        else:
58            d[exponents[i]] = coefs[i]
59    solution = " + ".join([f"{d[k]}x^{{{k}}}" for k in sorted(d)])
60
61    return f'${problem}$', f'${solution}$'

Combine Like Terms

Ex. Problem Ex. Solution
$6x^{9} + 3x^{2} + 5x^{19} + 3x^{17}$ $3x^{2} + 6x^{9} + 3x^{17} + 5x^{19}$
def complex_quadratic(prob_type=0, max_range=10):
 64def complex_quadratic(prob_type=0, max_range=10):
 65    r"""Complex Quadratic Equation
 66
 67    | Ex. Problem | Ex. Solution |
 68    | --- | --- |
 69    | Find the roots of given Quadratic Equation $x^2 + 8x + 8 = 0$ | $((-1.172, -6.828)) = (\frac{-8 + \sqrt{32}}{2}, (\frac{-8 - \sqrt{32}}{2})$ |
 70    """
 71    if prob_type < 0 or prob_type > 1:
 72        print("prob_type not supported")
 73        print("prob_type = 0 for real roots problems ")
 74        print("prob_tpye = 1 for imaginary roots problems")
 75        return None
 76    if prob_type == 0:
 77        d = -1
 78        while d < 0:
 79            a = random.randrange(1, max_range)
 80            b = random.randrange(1, max_range)
 81            c = random.randrange(1, max_range)
 82
 83            d = (b**2 - 4 * a * c)
 84    else:
 85        d = 0
 86        while d >= 0:
 87            a = random.randrange(1, max_range)
 88            b = random.randrange(1, max_range)
 89            c = random.randrange(1, max_range)
 90
 91            d = (b**2 - 4 * a * c)
 92
 93    eq = ''
 94
 95    if a == 1:
 96        eq += 'x^2 + '
 97    else:
 98        eq += str(a) + 'x^2 + '
 99
100    if b == 1:
101        eq += 'x + '
102    else:
103        eq += str(b) + 'x + '
104
105    eq += str(c) + ' = 0'
106
107    problem = f'Find the roots of given Quadratic Equation ${eq}$'
108
109    if d < 0:
110        sqrt_d = (-d)**0.5
111
112        if sqrt_d - int(sqrt_d) == 0:
113            sqrt_d = int(sqrt_d)
114            solution = rf'(\frac{{{-b} + {sqrt_d}i}}{{{2*a}}}, \frac{{{-b} - {sqrt_d}i}}{{{2*a}}})'
115        else:
116            solution = rf'(\frac{{{-b} + \sqrt{{{-d}}}i}}{{{2*a}}}, \frac{{{-b} - \sqrt{{{-d}}}i}}{{{2*a}}})'
117
118        return problem, solution
119
120    else:
121        s_root1 = round((-b + (d)**0.5) / (2 * a), 3)
122        s_root2 = round((-b - (d)**0.5) / (2 * a), 3)
123
124        sqrt_d = (d)**0.5
125
126        if sqrt_d - int(sqrt_d) == 0:
127            sqrt_d = int(sqrt_d)
128            g_sol = rf'(\frac{{{-b} + {sqrt_d}}}{{{2*a}}}, \frac{{{-b} - {sqrt_d}}}{{{2*a}}})'
129        else:
130            g_sol = rf'(\frac{{{-b} + \sqrt{{{d}}}}}{{{2*a}}}, (\frac{{{-b} - \sqrt{{{d}}}}}{{{2*a}}})'
131
132        solution = f'$({s_root1, s_root2}) = {g_sol}$'
133
134        return problem, solution

Complex Quadratic Equation

Ex. Problem Ex. Solution
Find the roots of given Quadratic Equation $x^2 + 8x + 8 = 0$ $((-1.172, -6.828)) = (\frac{-8 + \sqrt{32}}{2}, (\frac{-8 - \sqrt{32}}{2})$
def compound_interest(max_principle=10000, max_rate=10, max_time=10):
137def compound_interest(max_principle=10000,
138                      max_rate=10,
139                      max_time=10):
140    r"""Compound Interest
141
142    | Ex. Problem | Ex. Solution |
143    | --- | --- |
144    | Compound interest for a principle amount of $2679$ dollars, $9$% rate of interest and for a time period of $3$ years is $=$ | $3469.38$ |
145    """
146    p = random.randint(1000, max_principle)
147    r = random.randint(1, max_rate)
148    n = random.randint(1, max_time)
149    a = round(p * (1 + r / 100)**n, 2)
150
151    problem = f"Compound interest for a principle amount of ${p}$ dollars, ${r}$% rate of interest and for a time period of ${n}$ years is $=$"
152    return problem, f'${a}$'

Compound Interest

Ex. Problem Ex. Solution
Compound interest for a principle amount of $2679$ dollars, $9$% rate of interest and for a time period of $3$ years is $=$ $3469.38$
def distance_two_points(max_val_xy=20, min_val_xy=-20):
155def distance_two_points(max_val_xy=20, min_val_xy=-20):
156    r"""Distance between 2 points
157
158    | Ex. Problem | Ex. Solution |
159    | --- | --- |
160    | Find the distance between $(-19, -6)$ and $(15, -16)$ | $\sqrt{1256}$ |
161    """
162    point1X = random.randint(min_val_xy, max_val_xy + 1)
163    point1Y = random.randint(min_val_xy, max_val_xy + 1)
164    point2X = random.randint(min_val_xy, max_val_xy + 1)
165    point2Y = random.randint(min_val_xy, max_val_xy + 1)
166
167    distanceSq = (point1X - point2X) ** 2 + (point1Y - point2Y) ** 2
168
169    solution = rf"$\sqrt{{{distanceSq}}}$"
170    problem = f"Find the distance between $({point1X}, {point1Y})$ and $({point2X}, {point2Y})$"
171    return problem, solution

Distance between 2 points

Ex. Problem Ex. Solution
Find the distance between $(-19, -6)$ and $(15, -16)$ $\sqrt{1256}$
def expanding(range_x1=10, range_x2=10, range_a=10, range_b=10):
174def expanding(range_x1=10,
175              range_x2=10,
176              range_a=10,
177              range_b=10):
178    r"""Expanding Factored Binomial
179
180    | Ex. Problem | Ex. Solution |
181    | --- | --- |
182    |$(x-6)(-3x-3)$ | $x^2+18x+18$ |
183    """
184    x1 = random.randint(-range_x1, range_x1)
185    x2 = random.randint(-range_x2, range_x2)
186    a = random.randint(-range_a, range_a)
187    b = random.randint(-range_b, range_b)
188
189    def intParser(z):
190        if (z > 0):
191            return f"+{z}"
192        elif (z < 0):
193            return f"-{abs(z)}"
194        else:
195            return ""
196
197    c1 = intParser(a * b)
198    c2 = intParser((a * x2) + (b * x1))
199    c3 = intParser(x1 * x2)
200
201    p1 = intParser(a)
202    p2 = intParser(x1)
203    p3 = intParser(b)
204    p4 = intParser(x2)
205
206    if p1 == "+1":
207        p1 = ""
208    elif len(p1) > 0 and p1[0] == "+":
209        p1 = p1[1:]
210    if p3 == "+1":
211        p3 = ""
212    elif p3[0] == "+":
213        p3 = p3[1:]
214
215    if c1 == "+1":
216        c1 = ""
217    elif len(c1) > 0 and c1[0] == "+":
218        c1 = c1[1:]  # Cuts off the plus for readability
219    if c2 == "+1":
220        c2 = ""
221
222    problem = f"$({p1}x{p2})({p3}x{p4})$"
223    solution = f"${c1}x^2{c2}x{c3}$"
224    return problem, solution

Expanding Factored Binomial

Ex. Problem Ex. Solution
$(x-6)(-3x-3)$ $x^2+18x+18$
def factoring(range_x1=10, range_x2=10):
227def factoring(range_x1=10, range_x2=10):
228    r"""Factoring Quadratic
229    Given a quadratic equation in the form x^2 + bx + c, factor it into it's roots (x - x1)(x -x2)
230
231    | Ex. Problem | Ex. Solution |
232    | --- | --- |
233    | $x^2+2x-24$ | $(x-4)(x+6)$ |
234    """
235    x1 = random.randint(-range_x1, range_x1)
236    x2 = random.randint(-range_x2, range_x2)
237
238    def intParser(z):
239        if (z > 0):
240            return f"+{z}"
241        elif (z < 0):
242            return f"-{abs(z)}"
243        else:
244            return ""
245
246    b = intParser(x1 + x2)
247    c = intParser(x1 * x2)
248
249    if b == "+1":
250        b = "+"
251    if b == "":
252        problem = f"x^2{c}"
253    else:
254        problem = f"x^2{b}x{c}"
255
256    x1 = intParser(x1)
257    x2 = intParser(x2)
258    solution = f"$(x{x1})(x{x2})$"
259    return f"${problem}$", solution

Factoring Quadratic Given a quadratic equation in the form x^2 + bx + c, factor it into it's roots (x - x1)(x -x2)

Ex. Problem Ex. Solution
$x^2+2x-24$ $(x-4)(x+6)$
def int_matrix_22_determinant(max_matrix_val=100):
262def int_matrix_22_determinant(max_matrix_val=100):
263    r"""Determinant to 2x2 Matrix
264
265    | Ex. Problem | Ex. Solution |
266    | --- | --- |
267    | $\det \begin{bmatrix} 88 & 40 \\\ 9 & 91 \end{bmatrix}= $ | $7648$ |
268    """
269    a = random.randint(0, max_matrix_val)
270    b = random.randint(0, max_matrix_val)
271    c = random.randint(0, max_matrix_val)
272    d = random.randint(0, max_matrix_val)
273
274    determinant = a * d - b * c
275    lst = [[a, b], [c, d]]
276
277    problem = rf"$\det {bmatrix(lst)}= $"
278    solution = f"${determinant}$"
279    return problem, solution

Determinant to 2x2 Matrix

Ex. Problem Ex. Solution
$\det \begin{bmatrix} 88 & 40 \\ 9 & 91 \end{bmatrix}= $ $7648$
def intersection_of_two_lines( min_m=-10, max_m=10, min_b=-10, max_b=10, min_denominator=1, max_denominator=6):
282def intersection_of_two_lines(min_m=-10,
283                              max_m=10,
284                              min_b=-10,
285                              max_b=10,
286                              min_denominator=1,
287                              max_denominator=6):
288    r"""Intersection of two lines
289
290    | Ex. Problem | Ex. Solution |
291    | --- | --- |
292    | Find the point of intersection of the two lines: $y = \frac{-2}{6}x + 3$ and $y = \frac{3}{6}x - 8$ | $(\frac{66}{5}, \frac{-7}{5})$ |
293    """
294    def generateEquationString(m, b):
295        """
296        Generates an equation given the slope and intercept.
297        It handles cases where m is fractional.
298        It also ensures that we don't have weird signs such as y = mx + -b.
299        """
300        if m[0] == 0:
301            m = 0
302        elif abs(m[0]) == abs(m[1]):
303            m = m[0] // m[1]
304        elif m[1] == 1:
305            m = m[0]
306        else:
307            m = rf"\frac{{{m[0]}}}{{{m[1]}}}"
308        base = "y ="
309        if m != 0:
310            if m == 1:
311                base = f"{base} x"
312            elif m == -1:
313                base = f"{base} -x"
314            else:
315                base = f"{base} {m}x"
316        if b > 0:
317            if m == 0:
318                return f"{base} {b}"
319            else:
320                return f"{base} + {b}"
321        elif b < 0:
322            if m == 0:
323                return f"{base} -{b * -1}"
324            else:
325                return f"{base} - {b * -1}"
326        else:
327            if m == 0:
328                return f"{base} 0"
329            else:
330                return base
331
332    def fractionToString(x):
333        """
334        Converts the given fractions.Fraction into a string.
335        """
336        if x.denominator == 1:
337            x = x.numerator
338        else:
339            x = rf"\frac{{{x.numerator}}}{{{x.denominator}}}"
340        return x
341
342    m1 = (random.randint(min_m,
343                         max_m), random.randint(min_denominator, max_denominator))
344    m2 = (random.randint(min_m,
345                         max_m), random.randint(min_denominator, max_denominator))
346
347    b1 = random.randint(min_b, max_b)
348    b2 = random.randint(min_b, max_b)
349
350    eq1 = generateEquationString(m1, b1)
351    eq2 = generateEquationString(m2, b2)
352
353    problem = f"Find the point of intersection of the two lines: ${eq1}$ and ${eq2}$"
354
355    m1 = fractions.Fraction(*m1)
356    m2 = fractions.Fraction(*m2)
357    # if m1 == m2 then the slopes are equal
358    # This can happen if both line are the same
359    # Or if they are parallel
360    # In either case there is no intersection
361
362    if m1 == m2:
363        solution = "No Solution"
364    else:
365        intersection_x = (b1 - b2) / (m2 - m1)
366        intersection_y = ((m2 * b1) - (m1 * b2)) / (m2 - m1)
367        solution = f"$({fractionToString(intersection_x)}, {fractionToString(intersection_y)})$"
368
369    return problem, solution

Intersection of two lines

Ex. Problem Ex. Solution
Find the point of intersection of the two lines: $y = \frac{-2}{6}x + 3$ and $y = \frac{3}{6}x - 8$ $(\frac{66}{5}, \frac{-7}{5})$
def invert_matrix( square_matrix_dimension=3, max_matrix_element=99, only_integer_elements_in_inverted_matrixe=True):
372def invert_matrix(square_matrix_dimension=3,
373                  max_matrix_element=99,
374                  only_integer_elements_in_inverted_matrixe=True):
375    r"""Invert Matrix
376
377    | Ex. Problem | Ex. Solution |
378    | --- | --- |
379    | Inverse of Matrix $\begin{bmatrix} 4 & 1 & 4 \\\ 5 & 1 & 5 \\\ 12 & 3 & 13 \end{bmatrix}$ is: | $\begin{bmatrix} 2 & 1 & -1 \\\ 5 & -4 & 0 \\\ -3 & 0 & 1 \end{bmatrix}$ |
380    """
381    if only_integer_elements_in_inverted_matrixe is True:
382        isItOk = False
383        Mat = list()
384        while (isItOk is False):
385            Mat = list()
386            for i in range(0, square_matrix_dimension):
387                z = list()
388                for j in range(0, square_matrix_dimension):
389                    z.append(0)
390                z[i] = 1
391                Mat.append(z)
392            MaxAllowedMatrixElement = math.ceil(
393                pow(max_matrix_element, 1 / (square_matrix_dimension)))
394            randomlist = random.sample(range(0, MaxAllowedMatrixElement + 1),
395                                       square_matrix_dimension)
396
397            for i in range(0, square_matrix_dimension):
398                if i == square_matrix_dimension - 1:
399                    Mat[0] = [
400                        j + (k * randomlist[i])
401                        for j, k in zip(Mat[0], Mat[i])
402                    ]
403                else:
404                    Mat[i + 1] = [
405                        j + (k * randomlist[i])
406                        for j, k in zip(Mat[i + 1], Mat[i])
407                    ]
408
409            for i in range(1, square_matrix_dimension - 1):
410                Mat[i] = [
411                    sum(i) for i in zip(Mat[square_matrix_dimension - 1], Mat[i])
412                ]
413
414            isItOk = True
415            for i in Mat:
416                for j in i:
417                    if j > max_matrix_element:
418                        isItOk = False
419                        break
420                if isItOk is False:
421                    break
422
423        random.shuffle(Mat)
424        Mat = sympy.Matrix(Mat)
425        Mat = sympy.Matrix.transpose(Mat)
426        Mat = Mat.tolist()
427        random.shuffle(Mat)
428        Mat = sympy.Matrix(Mat)
429        Mat = sympy.Matrix.transpose(Mat)
430
431    else:
432        randomlist = list(sympy.primerange(0, max_matrix_element + 1))
433        plist = random.sample(randomlist, square_matrix_dimension)
434        randomlist = random.sample(
435            range(0, max_matrix_element + 1),
436            square_matrix_dimension * square_matrix_dimension)
437        randomlist = list(set(randomlist) - set(plist))
438        n_list = random.sample(
439            randomlist, square_matrix_dimension * (square_matrix_dimension - 1))
440        Mat = list()
441        for i in range(0, square_matrix_dimension):
442            z = list()
443            z.append(plist[i])
444            for j in range(0, square_matrix_dimension - 1):
445                z.append(n_list[(i * square_matrix_dimension) + j - i])
446            random.shuffle(z)
447            Mat.append(z)
448        Mat = sympy.Matrix(Mat)
449
450    problem = 'Inverse of Matrix $' + bmatrix(Mat.tolist()) + '$ is:'
451    solution = f'${bmatrix(sympy.Matrix.inv(Mat).tolist())}$'
452    return problem, solution

Invert Matrix

Ex. Problem Ex. Solution
Inverse of Matrix $\begin{bmatrix} 4 & 1 & 4 \\ 5 & 1 & 5 \\ 12 & 3 & 13 \end{bmatrix}$ is: $\begin{bmatrix} 2 & 1 & -1 \\ 5 & -4 & 0 \\ -3 & 0 & 1 \end{bmatrix}$
def linear_equations(n=2, var_range=20, coeff_range=20):
455def linear_equations(n=2, var_range=20, coeff_range=20):
456    r"""Linear Equations
457
458    | Ex. Problem | Ex. Solution |
459    | --- | --- |
460    | Given the equations $10x + -20y = 310$ and $-16x + -17y = 141$, solve for $x$ and $y$ | $x = 5$, $y = -13$ |
461    """
462    if n > 10:
463        print("[!] n cannot be greater than 10")
464        return None, None
465
466    vars = ['x', 'y', 'z', 'a', 'b', 'c', 'd', 'e', 'f', 'g'][:n]
467    soln = [random.randint(-var_range, var_range) for i in range(n)]
468    problem = list()
469    solution = "$, $".join(
470        ["{} = {}".format(vars[i], soln[i]) for i in range(n)])
471
472    for _ in range(n):
473        coeff = [random.randint(-coeff_range, coeff_range) for i in range(n)]
474        res = sum([coeff[i] * soln[i] for i in range(n)])
475        prob = [
476            "{}{}".format(coeff[i], vars[i]) if coeff[i] != 0 else ""
477            for i in range(n)
478        ]
479
480        while "" in prob:
481            prob.remove("")
482        prob = " + ".join(prob) + " = " + str(res)
483        problem.append(prob)
484
485    # problem = "\n".join(problem)
486    problem = "$ and $".join(problem)
487
488    return f'Given the equations ${problem}$, solve for $x$ and $y$', f'${solution}$'

Linear Equations

Ex. Problem Ex. Solution
Given the equations $10x + -20y = 310$ and $-16x + -17y = 141$, solve for $x$ and $y$ $x = 5$, $y = -13$
def line_equation_from_2_points(max_val=20):
491def line_equation_from_2_points(max_val=20):
492    r"""Equation of Line from Two Points
493
494    | Ex. Problem | Ex. Solution |
495    | --- | --- |
496    | Find the equation of the line passing through the points $(-19,-8)$ and $(-2,0)$. | $y=\frac{8}{17}x+\frac{16}{17}$ |
497    """
498    x1 = random.randint(-max_val, max_val)
499    x2 = random.randint(-max_val, max_val)
500    if x1 == x2:
501        return line_equation_from_2_points(max_val=max_val)
502    y1 = random.randint(-max_val, max_val)
503    y2 = random.randint(-max_val, max_val)
504    m1 = (y2 - y1) // math.gcd(y2 - y1, x2 - x1)
505    m2 = (x2 - x1) // math.gcd(y2 - y1, x2 - x1)
506    c1 = (y1 * (x2 - x1) - (y2 - y1) * x1) // math.gcd(y1 * (x2 - x1) - (y2 - y1) * x1, (x2 - x1))
507    c2 = (x2 - x1) // math.gcd(y1 * (x2 - x1) - (y2 - y1) * x1, (x2 - x1))
508    c = rf"{'+' if c1 >= 0 else '-'}\frac{{{abs(c1)}}}{{{c2}}}" if c1 != 0 else ""
509    if c2 < 0:
510        c2 = -c2
511        c1 = -c1
512        c = rf"{'+' if c1 >= 0 else '-'}\frac{{{abs(c1)}}}{{{c2}}}"
513    if c2 == 1:
514        c = f"{c1:+}"
515
516    problem = f'Find the equation of the line passing through the points $({x1},{y1})$ and $({x2},{y2})$.'
517
518    if m1 == 0:
519        return problem, f"$y={c}$"
520    if m2 < 0:
521        m1 = -m1
522        m2 = -m2
523    if m2 == 1:
524        if m1 == 1:
525            return problem, f"$y=x{c}$"
526        if m1 == -1:
527            return problem, f"$y=-x{c}$"
528        return problem, f"y={m1}x{c}"
529
530    return problem, rf"$y=\frac{{{m1}}}{{{m2}}}x{c}$"

Equation of Line from Two Points

Ex. Problem Ex. Solution
Find the equation of the line passing through the points $(-19,-8)$ and $(-2,0)$. $y=\frac{8}{17}x+\frac{16}{17}$
def log(max_base=3, max_val=8):
533def log(max_base=3, max_val=8):
534    r"""Logarithm
535
536    | Ex. Problem | Ex. Solution |
537    | --- | --- |
538    | $log_{3}(243)=$ | $5$ |
539    """
540    a = random.randint(1, max_val)
541    b = random.randint(2, max_base)
542    c = pow(b, a)
543
544    problem = f'$log_{{{b}}}({c})=$'
545    solution = f'${a}$'
546    return problem, solution

Logarithm

Ex. Problem Ex. Solution
$log_{3}(243)=$ $5$
def matrix_multiplication(max_val=100, max_dim=10):
549def matrix_multiplication(max_val=100, max_dim=10):
550    r"""Multiply Two Matrices
551
552    | Ex. Problem | Ex. Solution |
553    | --- | --- |
554    | Multiply $\begin{bmatrix} 15 & 72 \\\ 64 & -20 \\\ 18 & 59 \\\ -21 & -55 \\\ 20 & -12 \\\ -75 & -42 \\\ 47 & 89 \\\ -53 & 27 \\\ -56 & 44 \end{bmatrix}$ and $\begin{bmatrix} 49 & -2 & 68 & -28 \\\ 49 & 6 & 83 & 42 \end{bmatrix}$ | $\begin{bmatrix} 4263 & 402 & 6996 & 2604 \\\ 2156 & -248 & 2692 & -2632 \\\ 3773 & 318 & 6121 & 1974 \\\ -3724 & -288 & -5993 & -1722 \\\ 392 & -112 & 364 & -1064 \\\ -5733 & -102 & -8586 & 336 \\\ 6664 & 440 & 10583 & 2422 \\\ -1274 & 268 & -1363 & 2618 \\\ -588 & 376 & -156 & 3416 \end{bmatrix}$ |
555    """
556    m = random.randint(2, max_dim)
557    n = random.randint(2, max_dim)
558    k = random.randint(2, max_dim)
559
560    # generate matrices a and b
561    a = [[random.randint(-max_val, max_val) for _ in range(n)]
562         for _ in range(m)]
563    b = [[random.randint(-max_val, max_val) for _ in range(k)]
564         for _ in range(n)]
565
566    res = []
567    for r in range(m):
568        res.append([])
569        for c in range(k):
570            temp = 0
571            for t in range(n):
572                temp += a[r][t] * b[t][c]
573            res[r].append(temp)
574
575    problem = f"Multiply ${bmatrix(a)}$ and ${bmatrix(b)}$"
576    solution = f'${bmatrix(res)}$'
577    return problem, solution

Multiply Two Matrices

Ex. Problem Ex. Solution
Multiply $\begin{bmatrix} 15 & 72 \\ 64 & -20 \\ 18 & 59 \\ -21 & -55 \\ 20 & -12 \\ -75 & -42 \\ 47 & 89 \\ -53 & 27 \\ -56 & 44 \end{bmatrix}$ and $\begin{bmatrix} 49 & -2 & 68 & -28 \\ 49 & 6 & 83 & 42 \end{bmatrix}$ $\begin{bmatrix} 4263 & 402 & 6996 & 2604 \\ 2156 & -248 & 2692 & -2632 \\ 3773 & 318 & 6121 & 1974 \\ -3724 & -288 & -5993 & -1722 \\ 392 & -112 & 364 & -1064 \\ -5733 & -102 & -8586 & 336 \\ 6664 & 440 & 10583 & 2422 \\ -1274 & 268 & -1363 & 2618 \\ -588 & 376 & -156 & 3416 \end{bmatrix}$
def midpoint_of_two_points(max_value=20):
580def midpoint_of_two_points(max_value=20):
581    r"""Midpoint of two points
582
583    | Ex. Problem | Ex. Solution |
584    | --- | --- |
585    | The midpoint of $(-8,10)$ and $(18,0) = $ | $(5.0,5.0)$ |
586    """
587    x1 = random.randint(-20, max_value)
588    y1 = random.randint(-20, max_value)
589    x2 = random.randint(-20, max_value)
590    y2 = random.randint(-20, max_value)
591    xm = (x1 + x2) / 2
592    ym = (y1 + y2) / 2
593
594    problem = f"The midpoint of $({x1},{y1})$ and $({x2},{y2}) = $"
595    solution = f"$({xm},{ym})$"
596    return problem, solution

Midpoint of two points

Ex. Problem Ex. Solution
The midpoint of $(-8,10)$ and $(18,0) = $ $(5.0,5.0)$
def multiply_complex_numbers(min_real_imaginary_num=-20, max_real_imaginary_num=20):
599def multiply_complex_numbers(min_real_imaginary_num=-20,
600                             max_real_imaginary_num=20):
601    r"""Multiplication of 2 complex numbers
602
603    | Ex. Problem | Ex. Solution |
604    | --- | --- |
605    | $(14+18j) * (14+15j) = $ | $(-74+462j)$ |
606    """
607    num1 = complex(random.randint(min_real_imaginary_num, max_real_imaginary_num),
608                   random.randint(min_real_imaginary_num, max_real_imaginary_num))
609    num2 = complex(random.randint(min_real_imaginary_num, max_real_imaginary_num),
610                   random.randint(min_real_imaginary_num, max_real_imaginary_num))
611    product = num1 * num2
612
613    problem = f"${num1} * {num2} = $"
614    solution = f'${product}$'
615    return problem, solution

Multiplication of 2 complex numbers

Ex. Problem Ex. Solution
$(14+18j) * (14+15j) = $ $(-74+462j)$
def multiply_int_to_22_matrix(max_matrix_val=10, max_res=100):
618def multiply_int_to_22_matrix(max_matrix_val=10, max_res=100):
619    r"""Multiply Integer to 2x2 Matrix
620
621    | Ex. Problem | Ex. Solution |
622    | --- | --- |
623    | $5 * \begin{bmatrix} 1 & 0 \\\ 2 & 9 \end{bmatrix} =$ | $\begin{bmatrix} 5 & 0 \\\ 10 & 45 \end{bmatrix}$ |
624    """
625    a = random.randint(0, max_matrix_val)
626    b = random.randint(0, max_matrix_val)
627    c = random.randint(0, max_matrix_val)
628    d = random.randint(0, max_matrix_val)
629
630    constant = random.randint(0, int(max_res / max(a, b, c, d)))
631
632    a1 = a * constant
633    b1 = b * constant
634    c1 = c * constant
635    d1 = d * constant
636    lst = [[a, b], [c, d]]
637    lst1 = [[a1, b1], [c1, d1]]
638
639    problem = f'${constant} * {bmatrix(lst)} =$'
640    solution = f'${bmatrix(lst1)}$'
641    return problem, solution

Multiply Integer to 2x2 Matrix

Ex. Problem Ex. Solution
$5 * \begin{bmatrix} 1 & 0 \\ 2 & 9 \end{bmatrix} =$ $\begin{bmatrix} 5 & 0 \\ 10 & 45 \end{bmatrix}$
def quadratic_equation(max_val=100):
644def quadratic_equation(max_val=100):
645    r"""Quadratic Equation
646
647    | Ex. Problem | Ex. Solution |
648    | --- | --- |
649    | What are the zeros of the quadratic equation $22x^2+137x+25=0$ | ${-0.19, -6.04}$ |
650    """
651    a = random.randint(1, max_val)
652    c = random.randint(1, max_val)
653    b = random.randint(
654        round(math.sqrt(4 * a * c)) + 1, round(math.sqrt(4 * max_val * max_val)))
655    D = math.sqrt(b * b - 4 * a * c)
656    res = {round((-b + D) / (2 * a), 2), round((-b - D) / (2 * a), 2)}
657
658    problem = f"What are the zeros of the quadratic equation ${a}x^2+{b}x+{c}=0$"
659    solution = f'${res}$'
660    return problem, solution

Quadratic Equation

Ex. Problem Ex. Solution
What are the zeros of the quadratic equation $22x^2+137x+25=0$ ${-0.19, -6.04}$
def simple_interest(max_principle=10000, max_rate=10, max_time=10):
663def simple_interest(max_principle=10000,
664                    max_rate=10,
665                    max_time=10):
666    r"""Simple Interest
667
668    | Ex. Problem | Ex. Solution |
669    | --- | --- |
670    | Simple interest for a principle amount of $7217$ dollars, $3$% rate of interest and for a time period of $10$ years is $=$ | $2165.1$ |
671    """
672    p = random.randint(1000, max_principle)
673    r = random.randint(1, max_rate)
674    t = random.randint(1, max_time)
675    s = round((p * r * t) / 100, 2)
676
677    problem = f"Simple interest for a principle amount of ${p}$ dollars, ${r}$% rate of interest and for a time period of ${t}$ years is $=$ "
678    solution = f'${s}$'
679    return problem, solution

Simple Interest

Ex. Problem Ex. Solution
Simple interest for a principle amount of $7217$ dollars, $3$% rate of interest and for a time period of $10$ years is $=$ $2165.1$
def system_of_equations(range_x=10, range_y=10, coeff_mult_range=10):
682def system_of_equations(range_x=10,
683                        range_y=10,
684                        coeff_mult_range=10):
685    r"""Solve a System of Equations in R^2
686
687    | Ex. Problem | Ex. Solution |
688    | --- | --- |
689    | Given $-x + 5y = -28$ and $9x + 2y = 64$, solve for $x$ and $y$. | $x = 8$, $y = -4$ |
690    """
691    # Generate solution point first
692    x = random.randint(-range_x, range_x)
693    y = random.randint(-range_y, range_y)
694    # Start from reduced echelon form (coeffs 1)
695    c1 = [1, 0, x]
696    c2 = [0, 1, y]
697
698    def randNonZero():
699        return random.choice(
700            [i for i in range(-coeff_mult_range, coeff_mult_range) if i != 0])
701
702    # Add random (non-zero) multiple of equations (rows) to each other
703    c1_mult = randNonZero()
704    c2_mult = randNonZero()
705    new_c1 = [c1[i] + c1_mult * c2[i] for i in range(len(c1))]
706    new_c2 = [c2[i] + c2_mult * c1[i] for i in range(len(c2))]
707    # For extra randomness, now add random (non-zero) multiples of original rows
708    # to themselves
709    c1_mult = randNonZero()
710    c2_mult = randNonZero()
711    new_c1 = [new_c1[i] + c1_mult * c1[i] for i in range(len(c1))]
712    new_c2 = [new_c2[i] + c2_mult * c2[i] for i in range(len(c2))]
713
714    def coeffToFuncString(coeffs):
715        # lots of edge cases for perfect formatting!
716        x_sign = '-' if coeffs[0] < 0 else ''
717        # No redundant 1s
718        x_coeff = str(abs(coeffs[0])) if abs(coeffs[0]) != 1 else ''
719        # If x coeff is 0, dont include x
720        x_str = f'{x_sign}{x_coeff}x' if coeffs[0] != 0 else ''
721        # if x isn't included and y is positive, dont include operator
722        op = ' - ' if coeffs[1] < 0 else (' + ' if x_str != '' else '')
723        # No redundant 1s
724        y_coeff = abs(coeffs[1]) if abs(coeffs[1]) != 1 else ''
725        # Don't include if 0, unless x is also 0 (probably never happens)
726        y_str = f'{y_coeff}y' if coeffs[1] != 0 else (
727            '' if x_str != '' else '0')
728        return f'{x_str}{op}{y_str} = {coeffs[2]}'
729
730    problem = f"Given ${coeffToFuncString(new_c1)}$ and ${coeffToFuncString(new_c2)}$, solve for $x$ and $y$."
731    solution = f"$x = {x}$, $y = {y}$"
732    return problem, solution
733    # Add random (non-zero) multiple of equations to each other

Solve a System of Equations in R^2

Ex. Problem Ex. Solution
Given $-x + 5y = -28$ and $9x + 2y = 64$, solve for $x$ and $y$. $x = 8$, $y = -4$
def vector_cross(min_val=-20, max_val=20):
736def vector_cross(min_val=-20, max_val=20):
737    r"""Cross product of 2 vectors
738
739    | Ex. Problem | Ex. Solution |
740    | --- | --- |
741    | $[-1, -4, 10] \times [-11, 1, -16] = $ | $[54, -126, -45]$ |
742    """
743    a = [random.randint(min_val, max_val) for _ in range(3)]
744    b = [random.randint(min_val, max_val) for _ in range(3)]
745    c = [
746        a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
747        a[0] * b[1] - a[1] * b[0]
748    ]
749
750    problem = rf"${a} \times {b} = $"
751    solution = f"${c}$"
752    return problem, solution

Cross product of 2 vectors

Ex. Problem Ex. Solution
$[-1, -4, 10] \times [-11, 1, -16] = $ $[54, -126, -45]$
def vector_dot(min_val=-20, max_val=20):
755def vector_dot(min_val=-20, max_val=20):
756    r"""Dot product of 2 vectors
757
758    | Ex. Problem | Ex. Solution |
759    | --- | --- |
760    | $[12, -9, -8]\cdot[-9, 8, 1]=$ | $-188$ |
761    """
762    a = [random.randint(min_val, max_val) for i in range(3)]
763    b = [random.randint(min_val, max_val) for i in range(3)]
764    c = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
765
766    problem = rf'${a}\cdot{b}=$'
767    solution = f'${c}$'
768    return problem, solution

Dot product of 2 vectors

Ex. Problem Ex. Solution
$[12, -9, -8]\cdot[-9, 8, 1]=$ $-188$
def orthogonal_projection(min_val=-10, max_val=10):
771def orthogonal_projection(min_val=-10, max_val=10):
772    r"""Orthogonal Projection
773
774    | Ex. Problem | Ex. Solution |
775    | --- | --- |
776    | Find the orthogonal projection of $[2, 3]$ onto $[4, -7]$ | $[\frac{-4}{5}, \frac{7}{5}]$ |
777    """
778    v = [random.randint(min_val, max_val) for _ in range(2)]
779    u = [random.randint(min_val, max_val) for _ in range(2)]
780    dot_t = v[0] * u[0] + v[1] * u[1]
781    dot_b = u[0] * u[0] + u[1] * u[1]
782    frac = fractions.Fraction(dot_t, dot_b).limit_denominator()
783    y = [frac * u[0], frac * u[1]]
784
785    if y[0].denominator != 1:
786        y[0] = rf'\frac{{{y[0].numerator}}}{{{y[0].denominator}}}'
787    if y[1].denominator != 1:
788        y[1] = rf'\frac{{{y[1].numerator}}}{{{y[1].denominator}}}'
789
790    problem = f'Find the orthogonal projection of ${v}$ onto ${u}$'
791    solution = f'$[{y[0]}, {y[1]}]$'
792    return problem, solution

Orthogonal Projection

Ex. Problem Ex. Solution
Find the orthogonal projection of $[2, 3]$ onto $[4, -7]$ $[\frac{-4}{5}, \frac{7}{5}]$