In [6]:
%matplotlib inline

In [7]:
# imports goes here
import sympy # library for symbolic mathematics
import numpy as np # library for useful multiple functions
import matplotlib.pyplot as plt # plotting framework
import math # mathematical functions

High-School Maths Exercise - Solutions

Basic techniques and concepts for working with Jupyter Notebook, Python and Python libraries


Solution 1. Markdown

lets try some sorted numbered list

  1. this is the first point
    1. this is inclined point
    2. this is sedonc inclined point
  2. This is second main point

Now lets try unsorted list

  • this is a point
    • and this is inclined point
    • second indlined point
  • Again some point
    • this will have sublist
      • this is sublist
      • of few elements
      • handing here

One table

SoftUni Google
1. and if you click this
2. it will take you
3. to SoftUni or Google

Solution 2. Quadratic Equations - formulas and LaTex

We start with the equation $$ ax^2 + bx + c = 0 $$

We can try to get something like the sum of squares formula. Recall that $$ (px+q)^2 = p^2x^2 + 2pqx + q^2 $$

Let's take the first two terms ($ax^2 + bx$). We can see that they fit the formula above almost perfectly. We have $$ a = p^2, b = 2pq $$ $$ \Rightarrow p = \sqrt{a}, q = \frac{b}{2p} = \frac{b}{2\sqrt{a}}$$.

We also need to add $q^2=\frac{b^2}{4a}$. Since this is an equation, we have to add it to both sides of the original equation. We get: $$ p^2x^2 + 2pqx + q^2 + c = q^2$$

Now, express the equation above in terms of $a, b, c$:

Result:

$$ {\sqrt{a}}^2x^2 + 2\sqrt{a}\frac{b}{2\sqrt{a}}x + \frac{b^2}{4a} + c = \frac{b^2}{4a} $$ Place $c$ on the right-hand side. We now have our squared formula on the left:

Result:

$$ \sqrt{a}^2x^2 + 2\sqrt{a}\frac{b}{2\sqrt{a}}x + \frac{b^2}{4a} = \frac{b^2}{4a} - c $$ $$ \left(\sqrt{a}\right)^2x^2 + 2\left(\sqrt{a}\right)\left(\frac{b}{2\sqrt{a}}\right)x + \left(\frac{b}{2\sqrt{a}}\right)^2 = \frac{b^2}{4a} - c $$ $$ \left(\sqrt{a}x + \frac{b}{2\sqrt{a}}\right)^2 = \frac{b^2}{4a} - c $$ Take the square root of both sides. Note that this means just removing the second power on the left-hand side (because the number is positive) but the right-haand side can be positive or negative: $\pm$:

Result:

$$ \sqrt{a}x + \frac{b}{2\sqrt{a}} = \pm\sqrt{\frac{b^2}{4a} - \frac{4ac}{4a}} $$ $$ \sqrt{a}x + \frac{b}{2\sqrt{a}} = \pm\sqrt{\frac{b^2 - 4ac}{4a}} $$ You should get something like $\alpha x + \beta = \pm\sqrt{\frac{\gamma}{\delta}}$, where $\alpha, \beta, \gamma, \delta$ are all expresions. Now there's **only one term** containing $x$. Leave it to the left and transfer everything else to the right: $$ \sqrt{a}x = \pm\sqrt{\frac{b^2 - 4ac}{4a}} - \frac{b}{2\sqrt{a}}$$ To get $x$, divide both sides of the equation by the coefficient $\alpha$. Simplify the expression: $$ x = \left(\frac{\pm\sqrt{b^2 - 4ac}}{2\sqrt{a}} - \frac{b}{2\sqrt{a}}\right)\frac{1}{\sqrt{a}} \quad \Rightarrow \quad x = \frac{\pm\sqrt{b^2 - 4ac} - b}{2a} $$ If everything went OK, you should have got the familar expression for the roots of the quadratic equation: $$ x = \frac{-b \pm\sqrt{b^2 - 4ac}}{2a} $$ Let's play around some more. Remember *Vieta's formulas*? Let's very quickly calculate them. Express the sum and product of roots in terms of $a, b, c$. Substitute $x_1$ and $x_2$ for the two roots we just got. Simplify the result and you'll get that :)

Result:

$$ x_1 + x_2 = \frac{-b + \sqrt{b^2 - 4ac}}{2a} + \frac{-b - \sqrt{b^2 - 4ac}}{2a} $$ $$ x_1 + x_2 = \frac{-b + \sqrt{b^2 - 4ac} -b - \sqrt{b^2 - 4ac}}{2a} = \frac{-2b}{2a}$$ $$ x_1 + x_2 = -\frac{b}{a} $$ $$ x_1x_2= \frac{-b + \sqrt{b^2 - 4ac}}{2a}\cdot\frac{-b - \sqrt{b^2 - 4ac}}{2a} = \frac{\left(-b\right)^2 + b\sqrt{b^2 - 4ac} - b\sqrt{b^2 - 4ac} - \left(\sqrt{b^2 - 4ac}\right)^2}{4a^2} = \frac{b^2 - b^2 + 4ac}{4a^2} $$ $$ x_1x_2= \frac{c}{a} $$ If you worked correctly, you should have got the formulas $$x_1 + x_2 = -\frac{b}{a}, x_1x_2 = \frac{c}{a}$$ Now let's do something else. Let's **factor** the quadratic equation. This means, we'll just rearrange the terms so that they're more useful. Start again with the basic equation: $$ ax^2 + bx + c = 0 $$ Divide both sides of the equation by $a$:

Result:

$$ x^2 + \frac{b}{a}x + \frac{c}{a} = 0 $$

Now you get $b/a$ and $c/a$. Replace them with the sum and product of roots. Be very careful about the signs!

Result:

$$ x^2 -\left(x_1 + x_2\right)x + x_1x_2 = 0 $$

You should have some braces. Expand them:

Result:

$$ xx - xx_1 - xx_2 + x_1x_2 = 0 $$$$ \left(x - x_1\right)\left(x - x_2\right) = 0 $$

You should now get an expression containing $x$ (our variable) and $x_1, x_2$ (the roots). Please bear in mind those are different.

Find a way to group them and rearrange the symbols a bit. If you do this, you can arrive at the expression $$ (x - x_1)(x - x_2) = 0 $$

AHA! How is this formula useful? We can now "generate" a quadratic function by only knowing the roots. For example, generate a quadratic function which has roots -1 and 3. Write it in the form $ ax^2 + bx + c = 0 $:

Result:

$$ \left(x - \left(-1\right)\right)\left(x - 3\right) = 0 $$$$ x^2 - 3x + x -3 = 0 $$$$ x^2 - 2x - 3 = 0 $$

Solution 3. Solving with Python


In [8]:
# IMPORTANT, you should run second cell with import statements
# or current cell should contain 
# import sympy
x, a, b, c = sympy.symbols('x a b c') # Define symbols for parameters
sympy.init_printing() # LaTeX-formatted result for printing
sympy.solve(a * x**2 + b * x + c, x) # solve parametric equation


Out[8]:
$$\left [ \frac{1}{2 a} \left(- b + \sqrt{- 4 a c + b^{2}}\right), \quad - \frac{1}{2 a} \left(b + \sqrt{- 4 a c + b^{2}}\right)\right ]$$

In [9]:
import math
def solve_quadratic_equation(a, b, c):
    """
    Returns the real solutions of the quadratic equation ax^2 + bx + c = 0
    """
    # Check if we have linear equation, a = 0
    if a == 0: # if we do
        return [ -(c/b)] # return the single root
    # if not, we are continue with quadratic equation
    # determine the value of b**2 - 4ac
    d = float(b * b - 4.0 * a * c)
    if d < 0: # there is no roots
        return [] # return empty array
    else: #  we have some roots
        if d == 0: # only one root
            return [ (-b)/(2.0*a) ] 
        else: # or two roots
            return [(-b - (math.sqrt(d)))/(2.0*a), (-b + (math.sqrt(d)))/(2.0*a)]

In [10]:
# Testing: Execute this cell. The outputs should match the expected outputs. Feel free to write more tests
print(solve_quadratic_equation(1, -2, -1.25)) # [-0.5, 2.5] <== parameters were changed to apply to the result in the comment
print(solve_quadratic_equation(1, -1, -2)) # original parameters
print(solve_quadratic_equation(1, -8, 16)) # [4.0]
print(solve_quadratic_equation(1, 1, 1)) # []
print(solve_quadratic_equation(0, 2, 5))


[-0.5, 2.5]
[-1.0, 2.0]
[4.0]
[]
[-2.5]

Solution 4. Equation of a Line


In [11]:
x = np.linspace(-3, 5, 1000)
y = 2 * x + 3
ax = plt.gca()
ax.spines["bottom"].set_position("zero")
ax.spines["left"].set_position("zero")
ax.spines["top"].set_visible(False)
ax.spines["right"].set_visible(False)
yticks = ax.yaxis.get_major_ticks()
yticks[2].label1.set_visible(False)
plt.plot(x, y)
plt.show()



In [2]:
# source: gist.github.com/joferkington/3845684
def arrowed_spines(ax=None, arrow_length=20, labels=('',''), arrowprops=None):
    xlabel, ylabel = labels
    if ax is None:
        ax = plt.gca()
    if arrowprops is None:
        arrowprops = dict(arrowstyle='<|-', facecolor='black')
        
    for i, spine in enumerate(['left', 'bottom']):
        # Set up the annotation parameters
        t = ax.spines[spine].get_transform()
        xy, xycoords = [1, 0], ('axes fraction', t)
        xytext, textcoords = [arrow_length, 0], ('offset points', t)
        ha, va = 'left', 'bottom'
        
        # if axis is reversed, draw the arrow the other way
        top, bottom = ax.spines[spine].axis.get_view_interval()
        if top < bottom:
            xy[0] = 0
            xytext[0] *= -1
            ha, va = 'right', 'top'
            
        if spine is 'bottom':
            xarrow = ax.annotate(xlabel, xy, xycoords=xycoords, xytext=xytext,
                                textcoords=textcoords, ha=ha, va='center',
                                arrowprops=arrowprops)
        else:
            yarrow = ax.annotate(ylabel, xy[::-1], xycoords=xycoords[::-1],
                                xytext=xytext[::-1], textcoords=textcoords[::-1],
                                ha='center', va=va, arrowprops=arrowprops)
    return xarrow, yarrow

Solution 5. Linearizing function

Try to linearize $$ y = ae^{bx} $$


In [12]:
from sympy import *
sympy.init_printing()
x, a, b = sympy.symbols('x, a, b', extended_real=True)
#y = sympy.Function('y')
y = sympy.symbols('y')
eqs = sympy.Eq(y, a * exp(b * x))
lne = sympy.Eq(log(eqs.lhs), expand_log(log(eqs.rhs), force=True))
lne


Out[12]:
$$\log{\left (y \right )} = b x + \log{\left (a \right )}$$

Solution 6. Generalizing the plotting Function

Write a Python function wich takes another function, x range and number of points, and plots the function graph by evaluating ath every point.


In [13]:
def plot_math_function(f, min_x, max_x, num_points):
    """
    This function plots a graphic of given function 'f' in 2D Cartesian coordinate system
    use:
        plot_math_function(function 'f', minimum x, maximum x, number of points between min and max x)
    """
    # specify the range of points and transfer them to variable 'x'
    x = np.linspace(min_x, max_x, num_points)
    # assign to variable f_vectorized method from numpy library for vectorize according function 'f'
    # this allow us to use different functions 'f' to get the values for y
    f_vectorized = np.vectorize(f)
    # assign coresponding values for 'y'
    y = f_vectorized(x)
    # set alias/variable for pmatplotlib.pyplot.gca template for ploting
    fig, ax = plt.subplots() 
    # manipulate the plot object properties
        # insert the bottom and left axises to zero
    ax.spines["bottom"].set_position("zero") 
    ax.spines["left"].set_position("zero")
        # hide the top and right frame
    ax.spines["top"].set_visible(False) 
    ax.spines["right"].set_visible(False)
    # plot here, to populate ticks objects 
    plt.plot(x, y) 
    #plt.legend(loc='upper left')
    # extract ticks and set them to plt.subplots (ax)
    ax.set_yticklabels(ax.get_yticks())
    ax.set_xticklabels(ax.get_xticks())
    # create list of ticks labels
    ylabels = ax.get_yticklabels() 
    xlabels = ax.get_xticklabels() 
    # create variables for indexes from labels list where we are going to hide the labels 
    xzero = 0
    yzero = 0
    # loop trough labels and extract index of text '0.0'
    for num, xlabel in enumerate(xlabels, start=0):
        if xlabel.get_text() == '0.0':
            xzero = num
    for num, ylabel in enumerate(ylabels, start=0):
        if ylabel.get_text() == '0.0':
            yzero = num
    # another tuning of tick labels
    def fine_tunning():
        for label in ax.get_xticklabels() + ax.get_yticklabels():
            label.set_fontsize(10)
            label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65))
        plt.xlim(x.min() - 1, x.max() + 1)
        plt.ylim(y.min() * 1.1, y.max() * 1.1)
    # take all Y major ticks
    yticks = ax.yaxis.get_major_ticks() 
    xticks = ax.xaxis.get_major_ticks()
    ax.set_xlabel('x')
    ax.set_ylabel('y').set_rotation(0)
    # offset label for zero of X
    xticks[xzero].label1.set_horizontalalignment('right')
    # hide label1 on index with zero of Y
    yticks[yzero].label1.set_visible(False)
    # fine positioning of x label
    ax.xaxis.set_label_coords(1.05, yzero / len(ylabels)) 
    # possitioning of Y label
    ax.yaxis.set_label_coords((1 * abs(min_x))/((max_x) - (min_x)), 1.02) 
    fine_tunning()
    plt.show()

In [14]:
plot_math_function(lambda x: 2 * x + 3, -3, 5, 1000)
plot_math_function(lambda x: -x + 8, -1, 10, 1000)
plot_math_function(lambda x: x**2 - x - 2, -3, 4, 1000)
plot_math_function(lambda x: np.sin(x), -np.pi, np.pi, 1000)
plot_math_function(lambda x: np.sin(x) / x, -4 * np.pi, 4 * np.pi, 1000)


Solution 7. Solving Equations Graphically

Plot multiple functions on one graph


In [15]:
def plot_math_functions(functions, min_x, max_x, num_points):
    # Write your code here
    x = np.linspace(min_x, max_x, num_points)
    vectorized_fs = [np.vectorize(f) for f in functions]
    ys = [vectorized_f(x) for vectorized_f in vectorized_fs]
    fig, ax = plt.subplots() # set alias for pmatplotlib.pyplot.gca template for ploting
    # manipulate the plot object properties
    ax.spines["bottom"].set_position("zero") # insert the axis to zero
    ax.spines["left"].set_position("zero")
    ax.spines["top"].set_visible(False) # hide top frame
    ax.spines["right"].set_visible(False)
    for y in ys:
        plt.plot(x, y)
    ax.set_yticklabels(ax.get_yticks()) # extract ticks and set them to plt.subplots (ax)
    ax.set_xticklabels(ax.get_xticks())
    ylabels = ax.get_yticklabels() # create list of ticks labels
    xlabels = ax.get_xticklabels() 
    # create variables for indexes from labels list where we are going to hide the labels 
    xzero = 0
    yzero = 0
    # loop trough labels and extract index of text '0.0'
    for num, xlabel in enumerate(xlabels, start=0):
        if xlabel.get_text() == '0.0':
            xzero = num
    for num, ylabel in enumerate(ylabels, start=0):
        if ylabel.get_text() == '0.0':
            yzero = num
    yticks = ax.yaxis.get_major_ticks() # take all Y major ticks
    xticks = ax.xaxis.get_major_ticks()
    ax.set_xlabel('x') # we can have set_xlabel('name', fontsize = 12)
    ax.set_ylabel('y').set_rotation(0)
    # offset label for zero of X
    xticks[xzero].label1.set_horizontalalignment('right')
    # hide label1 on index with zero of Y
    yticks[yzero].label1.set_visible(False)
    ax.xaxis.set_label_coords(1.02, yzero / len(ylabels)) # fine positioning of x label
    ax.yaxis.set_label_coords((1 * abs(min_x))/((max_x) - (min_x)), 1.05) # possitioning of Y label
    plt.show()

In [16]:
plot_math_functions([lambda x: 2 * x + 3, lambda x: 0], -3, 5, 1000)
plot_math_functions([lambda x: 3 * x**2 - 2 * x + 5, lambda x: 3 * x + 7], -2, 3, 1000)



In [17]:
plot_math_functions([lambda x: (-4 * x + 7) / 3, lambda x: (-3 * x + 8) / 5, lambda x: (-x - 1) / -2], -1, 4, 1000)


Solution 8. Trigonometric functions

Use the plotting function you wrote above to plot the inverse trigonometric functions


In [18]:
plot_math_functions([lambda x: np.arcsin(x), lambda x: np.arccos(x), lambda x: np.arctan(x), lambda x: np.arctan(1/x)], -1.0, 1.0, 1000)


Solution 9. Equation of a Circle

Equation of a Circle


In [19]:
def plot_circle(x_c, y_c, r):
    """
    Plots the circle with center C(x_c; y_c) and radius r.
    This corresponds to plotting the equation x^2 + y^2 = r^2
    """
    # Write your code here
    plt.gca().set_aspect('equal')
    y = np.linspace(y_c -r - 1, y_c + r + 1, 30) 
    x = np.linspace(x_c - r - 1, x_c + r + 1, 30)
    x, y = np.meshgrid(x, y)
    circle = x ** 2 + y ** 2 - r ** 2
    plt.contour(x, y, circle, [0])
    plt.show()

In [20]:
plot_circle(0, 0, 2)



In [ ]: