'''
Created on 01-Apr-2021
@author: bthakur
'''
from functools import reduce

import numpy as np
import random
import inspect
import traceback
from sympy import (simplify, sympify, log, symbols, Eq, Matrix, latex,
                   solve, Rational, diag)

from xv.km.util import latex_fraction
from ._bivariate_expressions import BivariateExpressions

from ..helper import BaseHelper
from xv.km.managers import BaseManager
from xv.km.kelements import KProblemTemplate, KPrintElement
from sympy.core.expr import UnevaluatedExpr

from ..util import MathUtil
from xv.util import toIntOrFloat

class ArithmeticOperationManager(BaseManager):
    '''
    ArithmeticOperationManager
    Example:
        ke = ArithmeticOperationManager()
        ke.getRandomProblem()
        ke.getRandomProblem(problem_type = 0)
        ke.getRandomProblem(problem_type = 1)
        ...
        ke.printProblem()
        ke.printAnswer()
        ke.printSolution()
    '''

    def __new__(cls, *args, **kwargs):
        instance = super(ArithmeticOperationManager, cls).__new__(cls, *args, **kwargs)
        for base_class in ArithmeticOperationManager.__bases__:
            base_class.__init__(instance, *args, **kwargs)
        return instance

    def __init__(self, *args, **kwargs):
        self.base_helper = BaseHelper(**kwargs)
        self._equation = None
        pass



    def _getRandomArray(self, size, includeZero = True):
        signs = np.random.choice([1, -1], size)
        if includeZero:
            arr = np.random.randint(0, 10, size) * signs
        else:
            arr = np.random.randint(1, 10, size) * signs
        return arr
        pass

    def _getExprFromArr(self, arr):
        s = ""
        for idx, item in enumerate(arr):
            if item < 0:
                s = f"{s} - {0 - item}"
                pass
            else:
                s = f"{s} + {item}"
                pass
            pass
        return s.strip()
        pass

    def _getExprFromArrWithSign(self, arr, signs = None, showPlus = None):
        if showPlus is None:
            showPlus = random.choice([True, False])

        s = ""
        for idx, item in enumerate(arr):
            if signs[idx] == -1:
                s_sign = " - "
            else:
                s_sign = " + "

            if item < 0:
                s_item = f" (-{0 - item})"
                pass
            else:
                if showPlus:
                    s_item = f" (+{item})"
                else:
                    s_item = f" {item}"
                pass

            s = f"{s} {s_sign} {s_item}"

            pass

        s = s.strip()
        if not showPlus:
            if s[0] == "+":
                s = s[1:]

        return s.strip()
        pass

    def _splitArrPosNeg(self, arr):
        arrPos = [item for item in arr if item > 0]
        arrNeg = [item for item in arr if item < 0]
        return arrPos, arrNeg
        pass


    def _getProdExpr(self, arr, showPlus = None):
        if showPlus is None:
            showPlus = random.choice([True, False])

        s = ""
        for idx, item in enumerate(arr):

            if item < 0:
                s_item = f" (-{0 - item})"
                pass
            else:
                if showPlus:
                    s_item = f" (+{item})"
                else:
                    s_item = f" {item}"
                pass

            s = f"{s} * {s_item}"

            pass

        s = s.strip()
        if s[0] == "*":
            s = s[1:]

        return s.strip()
        pass

    def _get_randoms_minuses(self):
        signs = []
        for i in range(0, random.randint(3, 6)):
            s = ['-'] * random.randint(1, 5) + ['+'] * random.randint(1, 5)
            random.shuffle(s)
            s_size = random.randint(1, len(s)//2 + 1)
            s = s[:s_size]
            minus_count = s.count('-')
            sign_v = (-1) ** minus_count
            if sign_v == -1:
                sign_v = " - "
            else:
                sign_v = " + "

            if s_size < 2:
                sign_s = ''
            elif minus_count == 0:
                sign_s = 'all pluses multiplied together remains plus'
            elif minus_count == 1:
                sign_s = 'one minus results in minus'
            elif minus_count % 2 == 0:
                sign_s = f'even number of minuses multiplied results in plus'
            else:
                sign_s = f'odd number of minuses multiplied results in minus'

            signs.append([" ".join(s) , minus_count, sign_v, sign_s ])

        return signs
        pass

    def _get_problem_data_NOT_USED(self, n1, n2, op_type = "+", final_answer = False):
        signs = self._get_randoms_minuses()
        if op_type == '+':
            problem = f"""
            ${signs[0][0]} {n1} {signs[1][0]} {n2} $
            """
            comment = list(set([signs[0][3], signs[1][3]]))


            if len(comment) < 1:
                comment_str = ""
            else:
                comment_str = ",\n".join(
                                    [c for c in comment if c.strip()])
                comment_str = "\n" + comment_str

            expr = f"{signs[0][2]} {n1} {signs[1][2]} {n2}"
            step1 = f"$\\displaystyle = {expr}$"
            step2 = f"$\\displaystyle = {int(sympify(expr))}$"

            if final_answer:
                answer = f"""
                {problem.strip()}
                {step2}
                """
                solution = f"""
                {problem.strip()}
                {step1} {comment_str}
                {step2}
                """
            else:
                answer = f"""
                {problem.strip()}
                {step1}
                """
                solution = f"""
                {problem.strip()}
                {step1} {comment_str}
                """

            return {'problem': problem,
                    'answer': answer,
                    'solution': solution
                }

    def _get_minus_rule_statement(self, n1, n2):
        minus_rule_statement = f"""
        <b>Note: </b>
        A term without sign is positive:

        $+{n1} = {n1}$

        ${n1} = +{n1}$


        All immediate terms are multiplied. So,

        $\\displaystyle -- = - * -$

        $\\displaystyle -{n1} = - * {n1}$

        $\\displaystyle - +{n1} = - * + * {n1}$

        $\\displaystyle - -{n1} = - * - * {n1}$

        $+ -{n1} = + * - * {n1}$

        If minuses are multiplied, two minuses become plus. That means, even number of minuses becomes plus but odd number of minuses remain minus.

        $\\displaystyle -- = - * - = +$

        $\\displaystyle -{n1} = - * {n1} = -{n1}$

        $\\displaystyle - +{n1} = - * + * {n1} = -{n1}$

        $\\displaystyle - -{n1} = - * - * {n1} = {n1}$

        $+ -{n1} = + * - * {n1} = -{n1}$

        So, we can write

        $\\displaystyle -- = +$

        $\\displaystyle -{n1} = -{n1}$

        $\\displaystyle - +{n1} = -{n1}$

        $\\displaystyle - -{n1} = {n1}$

        $\\displaystyle - + -{n1} = {n1}$

        $\\displaystyle - - + -{n1} = -{n1}$

        $+ - -{n1} = {n1}$

        $\\displaystyle - - -{n1} = -{n1}$

        $\\displaystyle - - - -{n1} = {n1}$

        $\\displaystyle - - - - -{n1} = -{n1}$

        Therefore,

        $\\displaystyle - - {n1} + - {n2} $
        $\\displaystyle = {n1} - {n2} $ \t\t\t 2 minuses multiplied become plus


        $\\displaystyle - + {n1} + - {n2} $
        $\\displaystyle = - {n1} - {n2} $ \t\t\t 1 minus multiplied becomes minus


        """

        return minus_rule_statement.strip()
        pass

    def _get_signs(self, minus_count = None):
        if not minus_count is None:
            count = minus_count
        else:
            count = random.randint(0, 5)

        signs = ['-'] * count + ['+'] * random.randint(0, 2)

        if len(signs) < 1:
            signs = random.choice(['+', '-'])

        if not minus_count is None:
            signs = random.sample(signs, len(signs))
        else:
            signs = random.sample(signs, random.randint(1, len(signs)))

        return " ".join(signs)

    def get_sign(self, sign_str, omit_plus = False):
        v = sympify(f"{sign_str} 1")
        if v < 0:
            return "-"
        if omit_plus:
            return ""
        return "+"
        pass

    def _get_minus_question(self, n1, n2):
        sign11 = f"{ self._get_signs()}"
        sign12 = f"{ self._get_signs()}"
        step0 = f"{sign11} {n1} {sign12} {n2}"

        sign21 = self.get_sign(sign11, omit_plus = True)
        sign22 = self.get_sign(sign12, omit_plus = False)

        step1 = f"{sign21} {n1} {sign22} {n2}"
        step2 = sympify(f"{step1}")
        solution = [step0, step1, step2]
        return solution
        pass

    def _get_multiply_question(self, n1, n2):
        sign11 = f"{ self._get_signs()}"
        sign12 = f"{ self._get_signs()}"
        step0 = f"{sign11} {n1} * {sign12} {n2}"

        sign21 = self.get_sign(sign11, omit_plus = True)
        sign22 = self.get_sign(sign12, omit_plus = True)

        step1 = f"{sign21} {n1} * {sign22} {n2}"
        step2 = sympify(f"{step1}")
        solution = [step0, step1, step2]
        return solution
        pass

    def _get_multiply_three_numbers_question(self, n1, n2, n3):
        sign11 = f"{ self._get_signs()}"
        sign12 = f"{ self._get_signs()}"
        sign13 = f"{ self._get_signs()}"

        if random.choice([True, False]):
            step0 = f"{sign11} {n1} {sign12} {n2} * {sign13} {n3}"

            sign21 = self.get_sign(sign11, omit_plus = True)
            sign22 = self.get_sign(sign12, omit_plus = False)
            sign23 = self.get_sign(sign13, omit_plus = True)

            step1 = f"{sign21} {n1} {sign22} {n2} * {sign23} {n3}"
            step2 = f"{sign21} {n1} {sign22} ({n2} * {sign23} {n3})"

            step3_t2 = sympify(f"{sign22} {n2} * {sign23} {n3}")
            if step3_t2 > 0:
                step3_t2 = f"+ {abs(step3_t2)}"
            else:
                step3_t2 = f"- {abs(step3_t2)}"

            step3 = f"{sign21} {n1} {step3_t2}"

            step4 = sympify(f"{step0}")
        else:
            step0 = f"{sign11} {n1} * {sign12} {n2} {sign13} {n3}"

            sign21 = self.get_sign(sign11, omit_plus = True)
            sign22 = self.get_sign(sign12, omit_plus = True)
            sign23 = self.get_sign(sign13, omit_plus = False)

            step1 = f"{sign21} {n1} * {sign22} {n2} {sign23} {n3}"
            step2 = f"({sign21} {n1} * {sign22} {n2}) {sign23} {n3}"

            step3_t1 = sympify(f"{sign21} {n1} * {sign22} {n2}")
            step3 = f"{step3_t1} {sign23} {n3}"

            step4 = sympify(f"{step0}")
            pass
        solution = [step0, step1, step2, step3, step4]
        return solution
        pass



    def _init_problem_types(self, *args, **kwargs):
        self._append_problem_types([
            '_problem_learn_how_minuses_work',
            '_problem_learn_add',
            '_problem_learn_multiply',
            '_problem_learn_multiply_2',
            '_problem_learn_add_and_multiply',
            '_problem_learn_add_and_multiply_2',
            '_problem_express_add',
            '_problem_express_add_negative',
            '_problem_express_multiply',
            '_problem_add',
            '_problem_subtract',
            '_problem_additive_inverse',
            '_problem_multiply',
            '_problem_multiplicative_inverse',
            '_problem_divide',
            '_problem_multiply_divide',
            '_problem_pow_zero',
            '_problem_pow_pos_base',
            '_problem_pow_pos_exp',
            '_problem_pow_neg_exp',
            '_problem_exp_to_log',
            '_problem_negative_exp_to_log',
            '_problem_abs',
            '_problem_abs_advanced',
            '_problem_log',
            '_problem_log_advanced',
            '_problem_all_expressions',
            '_problem_all_expressions_n1_n2',
            '_problem_make_similar',
            '_problem_mixed_operations',
            ])
        pass

    def _problem_learn_how_minuses_work(self, *args, **kwargs):
        n1 = random.randint(1, 5)
        n2 = random.randint(n1+1, 9)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        q1 = self._get_minus_question(n1, n2)
        q2 = self._get_minus_question(n2, n1)
        q3 = self._get_minus_question(n1, n1)
        q4 = self._get_minus_question(n2, n2)
        minus_rule_statement = self._get_minus_rule_statement(n1, n2)

        problem_s = f"""
        Simplify multiple + or - signs:

        <b>Q1.</b>\t ${q1[0]}$

        <b>Q2.</b>\t ${q2[0]}$

        <b>Q3.</b>\t ${q3[0]}$

        <b>Q4.</b>\t ${q4[0]}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        Even number of odds becomes plus but odd number of minuses remain minus.

        <b>Q1.</b>\t
        ${q1[0]}$
        $\\displaystyle = {q1[1]}$


        <b>Q2.</b>\t
        ${q2[0]}$
        $\\displaystyle = {q2[1]}$


        <b>Q3.</b>\t
        ${q3[0]}$
        $\\displaystyle = {q3[1]}$


        <b>Q4.</b>\t
        ${q4[0]}$
        $\\displaystyle = {q4[1]}$

        {minus_rule_statement}
        """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        <b>Q1.</b>\t
        ${q1[0]} = {q1[1]}$

        <b>Q2.</b>\t
        ${q2[0]} = {q2[1]}$

        <b>Q3.</b>\t
        ${q3[0]} = {q3[1]}$

        <b>Q4.</b>\t
        ${q4[0]} = {q4[1]}$

        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate

    def _problem_learn_add(self, *args, **kwargs):
        n1 = random.randint(1, 5)
        n2 = random.randint(n1+1, 9)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        q1 = self._get_minus_question(n1, n2)
        q2 = self._get_minus_question(n2, n1)
        q3 = self._get_minus_question(n1, n1)
        q4 = self._get_minus_question(n2, n2)

        problem_s = f"""
        Solve:

        <b>Q1.</b>\t ${q1[0]}$

        <b>Q2.</b>\t ${q2[0]}$

        <b>Q3.</b>\t ${q3[0]}$

        <b>Q4.</b>\t ${q4[0]}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        <b>Note: </b>
        Let us assume there is a match between plus and minus. We have to find who wins and by how much.
        Also note, odd numbers of minues becomes minus and even numbers of minuses, becomes plus.


        <b>Q1.</b>\t
        ${q1[0]}$
        $\\displaystyle = {q1[1]}$
        $\\displaystyle = {q1[2]}$


        <b>Q2.</b>\t
        ${q2[0]}$
        $\\displaystyle = {q2[1]}$
        $\\displaystyle = {q2[2]}$


        <b>Q3.</b>\t
        ${q3[0]}$
        $\\displaystyle = {q3[1]}$
        $\\displaystyle = {q3[2]}$


        <b>Q4.</b>\t
        ${q4[0]}$
        $\\displaystyle = {q4[1]}$
        $\\displaystyle = {q4[2]}$

        """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        <b>Q1.</b>\t
        ${q1[0]} = {q1[2]}$

        <b>Q2.</b>\t
        ${q2[0]} = {q2[2]}$

        <b>Q3.</b>\t
        ${q3[0]} = {q3[2]}$

        <b>Q4.</b>\t
        ${q4[0]} = {q4[2]}$

        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_learn_multiply(self, *args, **kwargs):
        n1 = random.randint(1, 9)
        n2 = random.randint(1, 9)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""
        Solve the followings:

        <b>Q1.</b>\t $\\displaystyle - - - {n2}$

        <b>Q2.</b>\t $\\displaystyle - {-n1}$

        <b>Q3.</b>\t ${n1} * {n2}$

        <b>Q4.</b>\t ${-n1} * {n2}$

        <b>Q5.</b>\t ${n1} * {-n2}$

        <b>Q6.</b>\t ${-n1} * {-n2}$

        <b>Q7.</b>\t $\\displaystyle - - {n1} * {n2}$

        <b>Q8.</b>\t ${n1} * - - {n2}$

        <b>Q9.</b>\t $\\displaystyle - - {n1} * - - {n2}$

        <b>Q10.</b>\t $\\displaystyle - {n1} * - - {n2}$

        <b>Q11.</b>\t $\\displaystyle - - {n1} * - {n2}$

        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        <b>Note: </b>
        Multiply odd numbers of negatives, it gives negative.
        Multiply even numbers of negatives, it gives positive.

        <b>Q1.</b>\t
        $\\displaystyle - - - {n2} = -{n2}$ \t\t Three negative sign makes it negative

        <b>Q2.</b>\t
        $\\displaystyle - {-n1}= {n1}$ \t\t Two negative sign makes it positive

        <b>Q3.</b>\t
        ${n1} * {n2} = {n1 * n2}$

        <b>Q4.</b>\t
        ${-n1} * {n2} = -{n1 * n2}$ \t\t One negative sign makes it negative

        <b>Q5.</b>\t
        ${n1} * {-n2} = -{n1 * n2}$ \t\t One negative sign makes it negative

        <b>Q6.</b>\t
        ${-n1} * {-n2} = {n1 * n2}$ \t\t Two negative sign makes it positive

        <b>Q7.</b>\t
        $\\displaystyle - - {n1} * {n2} = {n1 * n2}$ \t\t Two negative sign makes it positive

        <b>Q8.</b>\t
        ${n1} * - - {n2} = {n1 * n2}$ \t\t Two negative sign makes it positive

        <b>Q9.</b>\t
        $\\displaystyle - - {n1} * - - {n2} = {n1 * n2}$ \t\t Four negative sign makes it positive

        <b>Q10.</b>\t
        $\\displaystyle - {n1} * - - {n2} = -{n1 * n2}$ \t\t Three negative sign makes it negative

        <b>Q11.</b>\t
        $\\displaystyle - - {n1} * - {n2} = -{n1 * n2}$ \t\t Three negative sign makes it negative
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""

        <b>Q1.</b>\t
        $\\displaystyle - - - {n2} = -{n2}$

        <b>Q2.</b>\t
        $\\displaystyle - {-n1}= {n1}$

        <b>Q3.</b>\t
        ${n1} * {n2} = {n1 * n2}$

        <b>Q4.</b>\t
        ${-n1} * {n2} = -{n1 * n2}$

        <b>Q5.</b>\t
        ${n1} * {-n2} = -{n1 * n2}$

        <b>Q6.</b>\t
        ${-n1} * {-n2} = {n1 * n2}$

        <b>Q7.</b>\t
        $\\displaystyle - - {n1} * {n2} = {n1 * n2}$

        <b>Q8.</b>\t
        ${n1} * - - {n2} = {n1 * n2}$

        <b>Q9.</b>\t
        $\\displaystyle - - {n1} * - - {n2} = {n1 * n2}$

        <b>Q10.</b>\t
        $\\displaystyle - {n1} * - - {n2} = -{n1 * n2}$

        <b>Q11.</b>\t
        $\\displaystyle - - {n1} * - {n2} = -{n1 * n2}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_learn_multiply_2(self, *args, **kwargs):
        n1 = random.randint(1, 5)
        n2 = random.randint(n1+1, 9)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        q1 = self._get_multiply_question(n1, n2)
        q2 = self._get_multiply_question(n2, n1)
        q3 = self._get_multiply_question(n1, n1)
        q4 = self._get_multiply_question(n2, n2)

        problem_s = f"""
        Solve:

        <b>Q1.</b>\t ${q1[0]}$

        <b>Q2.</b>\t ${q2[0]}$

        <b>Q3.</b>\t ${q3[0]}$

        <b>Q4.</b>\t ${q4[0]}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""

        <b>Q1.</b>\t
        ${q1[0]}$
        $\\displaystyle = {q1[1]}$
        $\\displaystyle = {q1[2]}$


        <b>Q2.</b>\t
        ${q2[0]}$
        $\\displaystyle = {q2[1]}$
        $\\displaystyle = {q2[2]}$


        <b>Q3.</b>\t
        ${q3[0]}$
        $\\displaystyle = {q3[1]}$
        $\\displaystyle = {q3[2]}$


        <b>Q4.</b>\t
        ${q4[0]}$
        $\\displaystyle = {q4[1]}$
        $\\displaystyle = {q4[2]}$

        """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        <b>Q1.</b>\t
        ${q1[0]} = {q1[2]}$

        <b>Q2.</b>\t
        ${q2[0]} = {q2[2]}$

        <b>Q3.</b>\t
        ${q3[0]} = {q3[2]}$

        <b>Q4.</b>\t
        ${q4[0]} = {q4[2]}$

        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_learn_add_and_multiply(self, *args, **kwargs):
        n1 = random.randint(1, 9)
        n2 = random.randint(1, 9)
        n3 = random.randint(1, 9)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""
        Solve the followings:

        <b>Q1.</b>\t
        ${n1} + {n2} * {n3}$

        <b>Q2.</b>\t
        ${n1} - {n2} * {n3}$

        <b>Q3.</b>\t
        $\\displaystyle - {n1} + {n2} * {n3}$

        <b>Q4.</b>\t
        $\\displaystyle - {n1} - {n2} * {n3}$

        <b>Q5.</b>\t
        $\\displaystyle - {n1} - {n2} * - {n3}$

        <b>Q6.</b>\t
        $ {n1} - {n2} * - {n3}$

        <b>Q7.</b>\t
        $ {n1} - {n2} * - - {n3}$

        <b>Q8.</b>\t
        $\\displaystyle - - {n1} - {n2} * + - {n3}$

        <b>Q9.</b>\t
        $\\displaystyle - {n1} - {n2} * - + - - {n3}$

        <b>Q10.</b>\t
        ${n1} - {n2} * - + - - {n3}$

        <b>Q11.</b>\t
        $\\displaystyle - + - {n1} * {n2}  - + - - {n3}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""

        <b>Q1.</b>\t
        ${n1} + {n2} * {n3}$
        $\\displaystyle = {n1} + \\left( {n2} * {n3} \\right) $
        $\\displaystyle = {n1} + {n2 * n3} $
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q2.</b>\t
        ${n1} - {n2} * {n3}$
        $\\displaystyle = {n1} - \\left( {n2} * {n3} \\right) $
        $\\displaystyle = {n1} - {n2 * n3} $
        $\\displaystyle = {n1 - n2 * n3}$


        <b>Q3.</b>\t
        $\\displaystyle - {n1} + {n2} * {n3}$
        $\\displaystyle = - {n1} + \\left( {n2} * {n3} \\right) $
        $\\displaystyle = - {n1} + {n2 * n3} $
        $\\displaystyle = {-n1 + n2 * n3}$


        <b>Q4.</b>\t
        $\\displaystyle - {n1} - {n2} * {n3}$
        $\\displaystyle = - {n1} - \\left( {n2} * {n3} \\right) $
        $\\displaystyle = - {n1} - {n2 * n3} $
        $\\displaystyle = {- n1 - n2 * n3}$


        <b>Q5.</b>\t
        $\\displaystyle - {n1} - {n2} * - {n3}$
        $\\displaystyle = - {n1} - \\left( {n2} * - {n3} \\right) $
        $\\displaystyle = - {n1} + {n2 * n3} $
        $\\displaystyle = {- n1 + n2 * n3}$


        <b>Q6.</b>\t
        $ {n1} - {n2} * - {n3}$
        $\\displaystyle = {n1} - \\left( {n2} * - {n3} \\right) $
        $\\displaystyle = {n1} + {n2 * n3} $
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q7.</b>\t
        $ {n1} - {n2} * - - {n3}$
        $\\displaystyle = {n1} - \\left( {n2} * {n3} \\right) $
        $\\displaystyle = {n1} - {n2 * n3} $
        $\\displaystyle = {n1 - n2 * n3}$


        <b>Q8.</b>\t
        $\\displaystyle - - {n1} - {n2} * + - {n3}$
        $\\displaystyle = {n1} - \\left( {n2} * - {n3} \\right) $
        $\\displaystyle = {n1} + {n2 * n3} $
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q9.</b>\t
        $\\displaystyle - {n1} - {n2} * - + - - {n3}$
        $\\displaystyle =- {n1} - \\left( {n2} * - {n3} \\right) $
        $\\displaystyle =- {n1} + {n2 * n3} $
        $\\displaystyle = {-n1 + n2 * n3}$


        <b>Q10.</b>\t
        ${n1} - {n2} * - + - - {n3}$
        $\\displaystyle = {n1} - \\left( {n2} * - {n3} \\right) $
        $\\displaystyle = {n1} + {n2 * n3} $
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q11.</b>\t
        $\\displaystyle - + - {n1} * {n2}  - + - - {n3}$
        $\\displaystyle = {n1} * {n2} - {n3}$
        $\\displaystyle = ({n1} * {n2}) - {n3}$
        $\\displaystyle = ({n1 * n2}) - {n3}$
        $\\displaystyle = {n1 * n2 - n3}$



        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""

        <b>Q1.</b>\t
        ${n1} + {n2} * {n3}$
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q2.</b>\t
        ${n1} - {n2} * {n3}$
        $\\displaystyle = {n1 - n2 * n3}$


        <b>Q3.</b>\t
        $\\displaystyle - {n1} + {n2} * {n3}$
        $\\displaystyle = {-n1 + n2 * n3}$


        <b>Q4.</b>\t
        $\\displaystyle - {n1} - {n2} * {n3}$
        $\\displaystyle = {- n1 - n2 * n3}$


        <b>Q5.</b>\t
        $\\displaystyle - {n1} - {n2} * - {n3}$
        $\\displaystyle = {- n1 + n2 * n3}$


        <b>Q6.</b>\t
        $ {n1} - {n2} * - {n3}$
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q7.</b>\t
        $ {n1} - {n2} * - - {n3}$
        $\\displaystyle = {n1 - n2 * n3}$


        <b>Q8.</b>\t
        $\\displaystyle - - {n1} - {n2} * + - {n3}$
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q9.</b>\t
        $\\displaystyle - {n1} - {n2} * - + - - {n3}$
        $\\displaystyle = {-n1 + n2 * n3}$


        <b>Q10.</b>\t
        ${n1} - {n2} * - + - - {n3}$
        $\\displaystyle = {n1 + n2 * n3}$


        <b>Q11.</b>\t
        $\\displaystyle - + - {n1} * {n2}  - + - - {n3}$
        $\\displaystyle = {n1 * n2 - n3}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate

    def _problem_learn_add_and_multiply_2(self, *args, **kwargs):
        n1 = random.randint(1, 9)
        n2 = random.randint(1, 9)
        n3 = random.randint(1, 9)


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        q1 = self._get_multiply_three_numbers_question(n1, n2, n3)
        q2 = self._get_multiply_three_numbers_question(n1, n2, n3)
        q3 = self._get_multiply_three_numbers_question(n1, n2, n3)
        q4 = self._get_multiply_three_numbers_question(n1, n2, n3)

        problem_s = f"""
        Solve:

        <b>Q1.</b>\t
        ${q1[0]}$

        <b>Q2.</b>\t
        ${q2[0]}$

        <b>Q3.</b>\t
        ${q3[0]}$

        <b>Q4.</b>\t
        ${q4[0]}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""

        <b>Q1.</b>\t
        ${q1[0]}$
        $\\displaystyle = {q1[1]}$
        $\\displaystyle = {q1[2]}$
        $\\displaystyle = {q1[3]}$
        $\\displaystyle = {q1[4]}$


        <b>Q2.</b>\t
        ${q2[0]}$
        $\\displaystyle = {q2[1]}$
        $\\displaystyle = {q2[2]}$
        $\\displaystyle = {q2[3]}$
        $\\displaystyle = {q2[4]}$


        <b>Q3.</b>\t
        ${q3[0]}$
        $\\displaystyle = {q3[1]}$
        $\\displaystyle = {q3[2]}$
        $\\displaystyle = {q3[3]}$
        $\\displaystyle = {q3[4]}$


        <b>Q4.</b>\t
        ${q4[0]}$
        $\\displaystyle = {q4[1]}$
        $\\displaystyle = {q4[2]}$
        $\\displaystyle = {q4[3]}$
        $\\displaystyle = {q4[4]}$

        """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        <b>Q1.</b>\t
        ${q1[0]} = {q1[4]}$

        <b>Q2.</b>\t
        ${q2[0]} = {q2[4]}$

        <b>Q3.</b>\t
        ${q3[0]} = {q3[4]}$

        <b>Q4.</b>\t
        ${q4[0]} = {q4[4]}$

        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_express_add(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        base = random.randint(1, 10)
        times = random.choice(
            [0, random.randint(0, 10), random.randint(11, 100)]
            )

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write an expression to add {base}, {times} times
        """
        problemTemplate.add_problem(statement)

        answer_s = f"""{base} * {times} = {base * times}"""

        if times == 0:
            soln_s = f"""
            Anything you add zero times, the result is zero.
            Therefore, the answer

            $\\displaystyle = {base} * {times}$

            $\\displaystyle = {answer_s}$
            """
        elif times > 9:
            soln_s = f"""
            ${base} + {base} + {base} + \\cdots {times}$ times

            $\\displaystyle = {base} * {times}$

            $\\displaystyle = {answer_s}$
            """
        else:
            s_sum = " + ".join([str(base) for i in  range(times)])
            soln_s = f"""
            {s_sum}

            $\\displaystyle = {base} * {times}$

            $\\displaystyle = {answer_s}$
            """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        problemTemplate.add_answer(f"$\\displaystyle {answer_s}$", 'text/html')

        return problemTemplate


    def _problem_express_add_negative(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        baseWithSign = - random.randint(1, 10)
        times = random.choice(
            [0, random.randint(0, 10), random.randint(11, 100)]
            )

        base = abs(baseWithSign)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write an expression to add {baseWithSign}, {times} times
        """
        problemTemplate.add_problem(statement)

        answer_s = f"""{baseWithSign} * {times} = {baseWithSign * times}"""

        if times == 0:
            soln_s = f"""
            Anything you add zero times is zero.
            Therefore, the answer

            $\\displaystyle = {baseWithSign * times}$

            $\\displaystyle = {answer_s}$
            """
        elif times == 1:
            soln_s = f"""
            $ {base}$

            $\\displaystyle = {answer_s}$
            """
        elif times > 9:
            soln_s = f"""
            $\\displaystyle - {base} - {base} - {base} - \\cdots {times} $ times

            $\\displaystyle = - {base} * {times}$

            $\\displaystyle = {answer_s}$ \t When you add negative numbers, you will get a negative number
            """
        else:
            s_sum = "".join([" - " + str(base) for i in  range(times)])
            soln_s = f"""
            ${s_sum}$

            $\\displaystyle = - {base} * {times}$

            $\\displaystyle = {answer_s}$ \t When you add negative numbers, you will get a negative number
            """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate



    def _problem_express_multiply(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        base = random.randint(1, 10) * random.choice([-1, 1])
        times = random.choice(
            [0, random.randint(0, 10), random.randint(11, 100)]
            )

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write an expression to multiply {base}, {times} times
        """
        problemTemplate.add_problem(statement)

        if base < 0:
            base_s = f"({base})"
        else:
            base_s = f"{base}"

        if base < 0 and times % 2 == 0:
            sign_comment = f"As the number of negatives {times} is even, the answer will be positive"
        elif base < 0 and times % 2 != 0:
            sign_comment = f"As the number of negatives {times} is odd, the answer will be negative"
        else:
            sign_comment = ""

        if times == 0:
            answer = 1
            answer_s = f"""
            {base_s} ^ {{{times}}} = {answer}
            """

            soln_s = f"""
            Anything you multiply zero times, the result is 1.

            Therefore, the answer

            $\\displaystyle = {base_s} ^ {{{times}}}$

            $\\displaystyle = {answer}$
            """
        elif times > 9:
            answer_s = f"""{base_s} ^ {{{times}}}"""

            soln_s = f"""
            ${base_s} * {base_s} * {base_s} \\;* \\cdots {times}$ times

            $\\displaystyle = {answer_s}$  \t {sign_comment}
            """
        else:
            answer_s = f"""{base_s} ^ {{{times}}}"""
            s_prod = " * ".join([str(base) for i in  range(times)])

            soln_s = f"""
            ${s_prod}$

            $\\displaystyle = {answer_s}$ \t {sign_comment}
            """

        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        problemTemplate.add_answer(f"$\\displaystyle {answer_s}$", 'text/html')

        return problemTemplate

    def _problem_add(self, *args, **kwargs):
        size = random.randint(2, 6)

        arr = self._getRandomArray(size)
        arr_expr = self._getExprFromArr(arr)
        arr_sum = sum(arr)

        arr_neg = [item for item in arr if item < 0]
        if len(arr_neg) != 0:
            arr_neg_expr = self._getExprFromArr(arr_neg)
            arr_neg_sum = sum(arr_neg)
        else:
            arr_neg_expr = ""
            arr_neg_sum = 0

        arr_pos = [item for item in arr if item > 0]
        if len(arr_pos) != 0:
            arr_pos_expr = self._getExprFromArr(arr_pos)
            arr_pos_sum = sum(arr_pos)
        else:
            arr_pos_expr = ""
            arr_pos_sum = 0

        statement = f"""Simplify the following:"""
        expr = KPrintElement(arr_expr, 'latex/html')
        answer = KPrintElement(f"$\\displaystyle {arr_sum}$", 'text/html')

        solution = []
        solution.append(KPrintElement(arr_expr, 'latex/html'))

        if (len(arr_neg) != 0 and
            len(arr_pos) != 0 and
            (len(arr_neg) > 0 or
             len(arr_pos) > 0)
            ):

            solution.append(KPrintElement(
                f"$\\displaystyle = {arr_pos_expr} {arr_neg_expr}$ \t\tSeggregate negative and positive numbers, ignore zeros",
                'text/html'))

            stmt_s = f"""$\\displaystyle = {arr_pos_sum} - {abs(arr_neg_sum)}$ \t\tSum negative and positive numbers separately"""
            solution.append(KPrintElement(stmt_s, 'text/html'))

            if arr_pos_sum != abs(arr_neg_sum):
                comment_s = f"""
                Deduct {min(arr_pos_sum, abs(arr_neg_sum))} from
                {max(arr_pos_sum, abs(arr_neg_sum))} and
                and put sign of larger one, {max(arr_pos_sum, abs(arr_neg_sum))}
                """
                solution.append(comment_s)
            pass

        solution.append(KPrintElement(
                f"$\\displaystyle = {arr_sum}$ ",
                'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_add',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_subtract(self, *args, **kwargs):
        size = random.randint(2, 6)
        signs = np.random.choice([1, -1], size)

        arr_with_sign = self._getRandomArray(size)
        arr_expr_with_sign = self._getExprFromArrWithSign(arr_with_sign, signs)

        arr = np.multiply(arr_with_sign, signs)
        arr_expr = self._getExprFromArr(arr)
        arr_sum = sum(arr)

        arr_neg = [item for item in arr if item < 0]
        if len(arr_neg) != 0:
            arr_neg_expr = self._getExprFromArr(arr_neg)
            arr_neg_sum = sum(arr_neg)
        else:
            arr_neg_expr = ""
            arr_neg_sum = 0

        arr_pos = [item for item in arr if item > 0]
        if len(arr_pos) != 0:
            arr_pos_expr = self._getExprFromArr(arr_pos)
            arr_pos_sum = sum(arr_pos)
        else:
            arr_pos_expr = ""
            arr_pos_sum = 0

        statement = f"""Simplify the following:"""
        expr = KPrintElement(arr_expr_with_sign, 'latex/html')
        answer = KPrintElement(f"{arr_sum}", 'text/html')

        solution = []
        solution.append(KPrintElement(f"$\\displaystyle {arr_expr_with_sign}$", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {arr_expr}$", 'text/html'))

        if (len(arr_neg) != 0 and
            len(arr_pos) != 0 and
            (len(arr_neg) > 0 or
             len(arr_pos) > 0)
            ):

            solution.append(KPrintElement(
                f"$\\displaystyle = {arr_pos_expr} {arr_neg_expr}$ \t\tSeggregate negative and positive numbers, ignore zeros",
                'text/html'))

            stmt_s = f"""$\\displaystyle = {arr_pos_sum} - {abs(arr_neg_sum)}$ \t\tSum negative and positive numbers separately"""
            solution.append(KPrintElement(stmt_s, 'text/html'))

            if arr_pos_sum != abs(arr_neg_sum):
                comment_s = f"""
                Deduct {min(arr_pos_sum, abs(arr_neg_sum))} from
                {max(arr_pos_sum, abs(arr_neg_sum))} and
                and put sign of larger one, {max(arr_pos_sum, abs(arr_neg_sum))}
                """
                solution.append(comment_s)
            pass

        solution.append(KPrintElement(
                f"$\\displaystyle = {arr_sum}$ ",
                'text/html'))



        problemTemplate = KProblemTemplate(
                problem_type = '_problem_subtract',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_additive_inverse(self, *args, **kwargs):
        ip_helper = self.base_helper.get_arithmetic_helper().get_integer_properties_helper()

        methods = [ip_helper.get_additive_inverse_int,
                   ip_helper.get_additive_inverse_int_expr]

        method = random.choice(methods)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        result = method(*args, **kwargs)
        if result is None:
            prob_s = f"""
            Failed to get the problem from {method.__name__}
            """
            problemTemplate.add_problem(prob_s.strip(), "text/html")
            pass

        problemTemplate.add_problem(result["prob_s"].strip(), "text/html")
        problemTemplate.add_solution(result["soln_s"].strip(), 'text/html')
        problemTemplate.add_answer(result["answer_s"].strip(), 'text/html')
        return problemTemplate

        return problemTemplate


    def _problem_multiply(self, *args, **kwargs):
        size = random.randint(2, 5)
        arr = self._getRandomArray(size, includeZero = False)
        arr_expr = self._getProdExpr(arr)
        arr_expr_without_plus = self._getProdExpr(arr, showPlus = False)

        arr_prod = reduce(lambda x, y: x * y, arr, 1)
        count_neg = len([item for item in arr if item < 0])

        statement = f"""Simplify the following:"""
        expr = KPrintElement(arr_expr, 'latex/html')
        answer = KPrintElement(f"{arr_prod}", 'text/html')

        solution = []
        solution.append(KPrintElement(arr_expr, 'latex/html'))
        solution.append(KPrintElement(f"= {arr_expr_without_plus}", 'latex/html'))


        if count_neg > 0:
            solution.append(KPrintElement(f"\nIgnore signs and multiply: {abs(arr_prod)}", 'text/html'))
            if count_neg % 2 == 0:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is even.
                So, the answer will be a positive a number.
                """
            else:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is odd.
                So, the answer will be a negative a number.
                """
            solution.append(KPrintElement(stmt_s, 'text/html'))
            pass

        solution.append(KPrintElement(f"\nTherefore, the answer is: ", 'text/html'))
        solution.append(KPrintElement(f"= {arr_prod}", 'latex/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_multiply',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_multiplicative_inverse(self, *args, **kwargs):
        ip_helper = self.base_helper.get_arithmetic_helper().get_integer_properties_helper()

        methods = [ip_helper.get_multiplicative_inverse_int,
                   ip_helper.get_multiplicative_inverse_int_expr]

        method = random.choice(methods)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        result = method(*args, **kwargs)
        if result is None:
            prob_s = f"""
            Failed to get the problem from {method.__name__}
            """
            problemTemplate.add_problem(prob_s.strip(), "text/html")
            pass

        problemTemplate.add_problem(result["prob_s"].strip(), "text/html")
        problemTemplate.add_solution(result["soln_s"].strip(), 'text/html')
        problemTemplate.add_answer(result["answer_s"].strip(), 'text/html')
        return problemTemplate

        return problemTemplate


    def _problem_divide(self, *args, **kwargs):
        size = 2
        arr = self._getRandomArray(size, includeZero = False)
        a = arr[0]
        b = arr[-1]
        arr_expr = f"Divide {a} by {b}"
        arr_expr_a_b = latex_fraction(f"{a}", f"{b}")

        if (a/b < 0):
            arr_expr_answer = "- " + latex_fraction(f"{abs(a)}", f"{abs(b)}")
        else:
            arr_expr_answer = latex_fraction(f"{abs(a)}", f"{abs(b)}")

        count_neg = len([item for item in arr if item < 0])

        statement = f"""Simplify the following:"""
        expr = KPrintElement(arr_expr, 'text/html')
        answer = KPrintElement(f"$\\displaystyle {arr_expr_answer}$", 'text/html')

        solution = []
        solution.append(KPrintElement(arr_expr, 'text/html'))

        if count_neg > 0:
            solution.append(KPrintElement(f"$\\displaystyle = {arr_expr_a_b}$", 'text/html'))
            if count_neg % 2 == 0:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is even.
                So, the answer will be a positive a number.
                """
            else:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is odd.
                So, the answer will be a negative a number.
                """
            solution.append(KPrintElement(stmt_s, 'text/html'))
            solution.append(KPrintElement(f"\nTherefore, the answer is: ", 'text/html'))
            pass

        solution.append(KPrintElement(f"$\\displaystyle = {arr_expr_answer}$", 'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_divide',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_multiply_divide(self, *args, **kwargs):
        """


        doc_style: xv_doc
        """

        size1 = random.randint(2, 5)
        arr1 = self._getRandomArray(size1, includeZero = False)
        arr1_expr = self._getProdExpr(arr1)
        arr1_expr_without_plus = self._getProdExpr(arr1, showPlus = False)
        arr1_abs_expr = self._getProdExpr([abs(x) for x in arr1], showPlus = False)

        arr1_prod = reduce(lambda x, y: x * y, arr1, 1)
        count1_neg = len([item for item in arr1 if item < 0])

        size2 = random.randint(2, 5)
        arr2 = self._getRandomArray(size2, includeZero = False)
        arr2_expr = self._getProdExpr(arr2)
        arr2_expr_without_plus = self._getProdExpr(arr2, showPlus = False)
        arr2_abs_expr = self._getProdExpr([abs(x) for x in arr2], showPlus = False)


        arr2_prod = reduce(lambda x, y: x * y, arr2, 1)
        count2_neg = len([item for item in arr2 if item < 0])

        size = 2
        arr = self._getRandomArray(size, includeZero = False)
        a = arr1_prod
        b = arr2_prod

        arr_expr = latex_fraction(f"{arr1_expr}", f"{arr2_expr}")
        arr_expr_without_plus = latex_fraction(f"{arr1_expr_without_plus}", f"{arr2_expr_without_plus}")

        if a/b > 0:
            arr_expr_a_b = latex_fraction(f"{abs(a)}", f"{abs(b)}")
        else:
            arr_expr_a_b = "- " + latex_fraction(f"{abs(a)}", f"{abs(b)}")
        arr_expr_answer = Rational(a, b)


        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""
        Simplify the following:

        $\\displaystyle {arr_expr}$
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        $\\displaystyle {arr_expr}$

        $\\displaystyle = {arr_expr_without_plus}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')


        count_neg = count1_neg + count2_neg
        if count_neg > 0:
            soln_s = f"""
            Ignore the signs and get values of numerator and denominator
            numerator = {arr1_abs_expr} = {abs(a)}
            denominator = {arr2_abs_expr} = {abs(b)}
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

            if count_neg % 2 == 0:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is even.
                So, the answer will be a positive a number.
                """
            else:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is odd.
                So, the answer will be a negative a number.
                """
            problemTemplate.add_solution(stmt_s.strip(), 'text/html')
            pass


        soln_s = f"""
        $\\displaystyle = {arr_expr_a_b}$

        $\\displaystyle = {arr_expr_answer}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {arr_expr_answer}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')
        return problemTemplate


    def _problem_multiply_divide_old(self, *args, **kwargs):
        size1 = random.randint(2, 5)
        arr1 = self._getRandomArray(size1, includeZero = False)
        arr1_expr = self._getProdExpr(arr1)
        arr1_expr_without_plus = self._getProdExpr(arr1, showPlus = False)
        arr1_abs_expr = self._getProdExpr([abs(x) for x in arr1], showPlus = False)

        arr1_prod = reduce(lambda x, y: x * y, arr1, 1)
        count1_neg = len([item for item in arr1 if item < 0])

        size2 = random.randint(2, 5)
        arr2 = self._getRandomArray(size2, includeZero = False)
        arr2_expr = self._getProdExpr(arr2)
        arr2_expr_without_plus = self._getProdExpr(arr2, showPlus = False)
        arr2_abs_expr = self._getProdExpr([abs(x) for x in arr2], showPlus = False)

        arr2_prod = reduce(lambda x, y: x * y, arr2, 1)
        count2_neg = len([item for item in arr2 if item < 0])

        size = 2
        arr = self._getRandomArray(size, includeZero = False)
        a = arr1_prod
        b = arr2_prod

        arr_expr = latex_fraction(f"{arr1_expr}", f"{arr2_expr}")
        arr_expr_without_plus = latex_fraction(f"{arr1_expr_without_plus}", f"{arr2_expr_without_plus}")

        if a/b > 0:
            arr_expr_a_b = latex_fraction(f"{abs(a)}", f"{abs(b)}")
        else:
            arr_expr_a_b = "- " + latex_fraction(f"{abs(a)}", f"{abs(b)}")
        arr_expr_answer = Rational(a, b)


        statement = f"""Simplify the following:"""
        expr = KPrintElement(f"$\\displaystyle {arr_expr}$", 'text/html')
        answer = KPrintElement(f"$\\displaystyle {arr_expr_answer}$", 'text/html')

        solution = []
        solution.append(KPrintElement(f"$\\displaystyle {arr_expr}$", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {arr_expr_without_plus}$", 'text/html'))

        count_neg = count1_neg + count2_neg
        if count_neg > 0:
            solution.append(KPrintElement(
                f"""Ignore the signs and get values of numerator and denominator
                numerator = {arr1_abs_expr} = {abs(a)}
                denominator = {arr2_abs_expr} = {abs(b)}
                """, 'text/html'))
            if count_neg % 2 == 0:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is even.
                So, the answer will be a positive a number.
                """
            else:
                stmt_s = f"""
                Count of negative numbers = {count_neg} which is odd.
                So, the answer will be a negative a number.
                """
            solution.append(KPrintElement(stmt_s, 'text/html'))
            pass

        solution.append(KPrintElement(f"$\\displaystyle = {arr_expr_a_b}$", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {arr_expr_answer}$", 'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_multiply_divide',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass



    def _problem_pow_zero(self, *args, **kwargs):
        size = 2
        a = 0
        b = random.randint(1, 6) * random.choice([-1, 1])

        statement = f"""Simplify:"""
        expr = KPrintElement(f"$ {a}^{{ {b} }} $", 'latex/html')

        solution = []
        solution.append(expr)
        if b == 0:
            solution.append("Anything to power zero is always 1")
        else:
            arr_str = self._express_power_as_multiply(
                        a, b, to_latex = True)
            solution.append(KPrintElement(f"$\\displaystyle = {arr_str} $", 'text/html'))

            if abs(b) != 1:
                solution.append(f"""You multiply zero with itself, it will be zero.
                So, any number of times you repeat it, it will be zero """)

            if b < 0:
                f_1_0 = latex_fraction("1", "0")
                solution.append(KPrintElement(f"$\\displaystyle = {f_1_0} $", 'text/html'))
                answer = f"""zero cannot be raised to a negative power."""
                stmt_s = f"""You cannot divide anything by zero.
                    So, {answer}."""

                solution.append(KPrintElement(f"{stmt_s}", 'text/html'))
            else:
                answer = f"{a ** b}"
                if b != 1:
                    solution.append(KPrintElement(f"= {answer}", 'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_pow_zero',
                problem = [statement, expr],
                answer = KPrintElement(f"{answer}", 'text/html'),
                solution = solution)

        return problemTemplate
        pass

    def _express_power_as_multiply(self, base, power, to_latex = True):
        if power < 0:
            arr_str = self._express_power_as_multiply(
                        base, abs(power), to_latex = False)

            if not to_latex:
                return f"1/({arr_str})"

            return latex_fraction("1", arr_str)

        if power < 10:
            arr = [str(base) for x in range(power)]
            arr_str = " * ".join(arr)
            if to_latex:
                return f"$\\displaystyle {arr_str}$"
            return arr_str
        else:
            arr_str = f"{base} * {base} * {base}"
            if to_latex:
                return f"$\\displaystyle {arr_str}$ \\cdots {power} times"
            return f"{arr_str} \\cdots {power} times"
        pass

    def _problem_pow_pos_base(self, *args, **kwargs):
        size = 2
        a = random.randint(0, 6)
        b = random.randint(0, 6)


        statement = f"""Simplify:"""
        expr = KPrintElement(f"$ {a}^{{ {b} }} $", 'latex/html')
        answer = KPrintElement(f"{a ** b}", 'latex/html')

        solution = []
        solution.append(expr)

        if b == 0:
            solution.append("Anything to power zero is always 1")

        if b != 0:
            expanded_expr = " * ".join([str(a) for i in range(b)])
            solution.append(KPrintElement(f"= {expanded_expr} ", 'latex/html'))

        solution.append(KPrintElement(f"= {a ** b}", 'latex/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_pow_pos_base',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_pow_pos_exp(self, *args, **kwargs):
        size = 2
        a = random.randint(0, 6) * random.choice([-1, 1])
        b = random.randint(0, 6)


        statement = f"""Simplify:"""
        if a < 0:
            expr = KPrintElement(f"$ {{ ({a}) }} ^{{ {b} }} $", 'latex/html')
        else:
            expr = KPrintElement(f"$ {a}^{{ {b} }} $", 'latex/html')

        answer = KPrintElement(f"{a ** b}", 'latex/html')

        solution = []
        solution.append(expr)

        if a < 0 and abs(a) != 1:
            a_abs = abs(a)
            res_sign = f"{{({-1})}}^{{ {b} }}"
            expanded_expr = f"{res_sign} * {{ {a_abs} }}^{{ {b} }}"
            solution.append(KPrintElement(f"$\\displaystyle = {expanded_expr} $", 'latex/html'))
            solution.append(KPrintElement(f"$\\displaystyle = {(-1) ** b} * {a_abs ** b} $", 'latex/html'))

        solution.append(KPrintElement(f"= {a ** b}", 'latex/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_pow_pos_exp',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_pow_neg_exp(self, *args, **kwargs):
        size = 2
        a = random.randint(1, 6) * random.choice([-1, 1])
        b = random.randint(1, 6) * (-1)


        statement = f"""Simplify:"""
        if a < 0:
            expr = KPrintElement(f"$ {{ ({a}) }} ^{{ {b} }} $", 'latex/html')
        else:
            expr = KPrintElement(f"$ {a}^{{ {b} }} $", 'latex/html')


        a_abs = abs(a)
        b_abs = abs(b)
        s_frac = latex_fraction("1", f"{a_abs} ^ {b_abs}")
        result_sign = (a // abs(a)) ** b_abs
        s_frac_sign = latex_fraction(f"{result_sign}", f"{a_abs} ^ {b_abs}")

        s_frac_ans = latex_fraction(f"{result_sign}", f"{a_abs ** b_abs}")

        answer = KPrintElement(f"$\\displaystyle = {s_frac_ans} $", 'latex/html')

        solution = []
        solution.append(expr)

        if a < 0 and abs(a) != 1:
            res_sign = f"{{({-1})}}^{{ {b} }}"
            expanded_expr = f"{res_sign} * {{ {a_abs} }}^{{ {b} }}"
            solution.append(KPrintElement(f"$\\displaystyle = {expanded_expr} $", 'latex/html'))

        b_abs = abs(b)
        s_frac = latex_fraction("1", f"{a_abs} ^ {b_abs}")

        if result_sign < 1:
            solution.append(KPrintElement(f"$\\displaystyle = {result_sign} * {s_frac} $", 'latex/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {s_frac_sign} $", 'latex/html'))

        solution.append(answer)

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_pow_neg_exp',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass


    def _problem_exp_to_log(self, *args, **kwargs):
        base = random.randint(2, 6)
        exp_exp = random.randint(1, 4)

        n = base ** exp_exp

        s_log_exp = f"""
        \log_{{ {base} }}{{ {base} ^ {{ {exp_exp} }}    }}
         """
        s_log_n = f"""
        \log_{{ {base} }}{{ {n} }}
         """

        statement = f"""Find log of {n} on base {base}"""
        expr = ""

        answer = exp_exp

        solution = []
        solution.append(f"log of {n} on base {base}")
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_n} $", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_exp} $", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {answer} $", 'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_log_advanced',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_negative_exp_to_log(self, *args, **kwargs):
        base = random.randint(2, 6)
        base_exp = random.randint(1, 4)

        n = base ** base_exp

        s_log_exp = f"""
        \log_{{ {base} ^ {{ {base_exp} }} }}{{ {base} }}
         """
        s_log_n = f"""
        \log_{{ {n} }}{{ {base} }}
         """

        statement = f"""Find log of {base} on base {n}"""
        expr = ""

        answer = latex_fraction("1", base_exp)

        solution = []
        solution.append(f"log of {base} on base {n}")
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_n} $", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_exp} $", 'text/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {answer} $", 'text/html'))

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_log_advanced',
                problem = [statement, expr],
                answer = KPrintElement(f"$\\displaystyle {answer} $", 'text/html'),
                solution = solution)

        return problemTemplate
        pass

    def _problem_log(self, *args, **kwargs):
        base = random.randint(2, 6)

        log_exp = - random.randint(1, 10)
        is_reversed_log_exp = False
        if random.choice([1, 1]) == -1:
            log_exp = Rational(1, log_exp)
            is_reversed_log_exp = True

        exp_exp = random.randint(1, 10)
        is_reversed_exp_exp = False
        if random.choice([1, 1]) == -1:
            exp_exp = Rational(1, exp_exp)
            is_reversed_exp_exp = True

        s_log_str = f"""
        \log_{{ {base} ^ {{ {log_exp} }}    }}{{ {base} ^ {{ {exp_exp} }}    }}
         """


        statement = f"""Simplify:
        """
        expr = KPrintElement(f"$ {s_log_str} $", 'latex/html')

        answer_frc = latex_fraction(exp_exp, log_exp)
        answer = KPrintElement(f"$ {answer_frc} $", 'latex/html')

        solution = []
        solution.append(expr)
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_str} $", 'latex/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {answer_frc} $", 'latex/html'))

        if is_reversed_log_exp and is_reversed_exp_exp:
            answer_frc_inv = latex_fraction(
                                f"{exp_exp.p} * {log_exp.q}",
                                f"{exp_exp.q} * {log_exp.p}")
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_inv} $", 'latex/html'))

            answer_frc_inv2 = latex_fraction(
                                f"{exp_exp.p * log_exp.q}",
                                f"{exp_exp.q * log_exp.p}")
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_inv2} $", 'latex/html'))

        if is_reversed_log_exp or is_reversed_exp_exp:
            answer_frc_simple = simplify(exp_exp / log_exp, rational = True)
            answer = KPrintElement(f"$ {answer_frc_simple} $", 'latex/html')
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_simple} $", 'latex/html'))
            pass

        if exp_exp * log_exp < -1:
            answer_frc = latex_fraction(- abs(exp_exp), abs(log_exp))
            answer = KPrintElement(f"$ {answer_frc} $", 'latex/html')

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_log_advanced',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass



    def _problem_log_advanced(self, *args, **kwargs):
        base = random.randint(2, 6)

        log_exp = - random.randint(1, 10)
        is_reversed_log_exp = False
        if random.choice([-1, 1]) == -1:
            log_exp = Rational(1, log_exp)
            is_reversed_log_exp = True

        exp_exp = random.randint(1, 10)
        is_reversed_exp_exp = False
        if random.choice([-1, 1]) == -1:
            exp_exp = Rational(1, exp_exp)
            is_reversed_exp_exp = True

        s_log_str = f"""
        \log_{{ {base} ^ {{ {log_exp} }}    }}{{ {base} ^ {{ {exp_exp} }}    }}
         """


        statement = f"""Simplify:
        """
        expr = KPrintElement(f"$ {s_log_str} $", 'latex/html')

        answer_frc = latex_fraction(exp_exp, log_exp)
        answer = KPrintElement(f"$ {answer_frc} $", 'latex/html')

        solution = []
        solution.append(expr)
        solution.append(KPrintElement(f"$\\displaystyle = {s_log_str} $", 'latex/html'))
        solution.append(KPrintElement(f"$\\displaystyle = {answer_frc} $", 'latex/html'))

        if is_reversed_log_exp and is_reversed_exp_exp:
            answer_frc_inv = latex_fraction(
                                f"{exp_exp.p} * {log_exp.q}",
                                f"{exp_exp.q} * {log_exp.p}")
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_inv} $", 'latex/html'))

            answer_frc_inv2 = latex_fraction(
                                f"{exp_exp.p * log_exp.q}",
                                f"{exp_exp.q * log_exp.p}")
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_inv2} $", 'latex/html'))

        if is_reversed_log_exp or is_reversed_exp_exp:
            answer_frc_simple = simplify(exp_exp / log_exp, rational = True)
            answer = KPrintElement(f"$ {answer_frc_simple} $", 'latex/html')
            solution.append(KPrintElement(f"$\\displaystyle = {answer_frc_simple} $", 'latex/html'))
            pass

        if exp_exp * log_exp < -1:
            answer_frc = latex_fraction(- abs(exp_exp), abs(log_exp))
            answer = KPrintElement(f"$ {answer_frc} $", 'latex/html')

        problemTemplate = KProblemTemplate(
                problem_type = '_problem_log_advanced',
                problem = [statement, expr],
                answer = answer,
                solution = solution)

        return problemTemplate
        pass

    def _problem_all_expressions(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        n = random.randint(1, 10)

        bve = BivariateExpressions(n, n)

        expr_and_result_labels = bve.get_expr_and_result_labels()

        exprs_solns_str = [f"<b>Solution {i+1}.</b>\n{x}"
                           for i, x in enumerate(expr_and_result_labels)]
        exprs_solns_str = "\n\n".join(exprs_solns_str)

        answers = bve.get_exprs(regex = True)
        exprs_answers_str = [f"<b>Answer {i+1}.</b>\n{x}"
                             for i, x in enumerate(answers)]
        exprs_answers_str = "\n\n".join(exprs_answers_str)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write all possible expressions and their values using {n} not more than twice.
        You can use {n} or {-n} if you want. Use +, -, /, power and log operators.
        """
        problemTemplate.add_problem(statement, 'text/html')

        problemTemplate.add_solution(exprs_solns_str, 'text/html')
        problemTemplate.add_answer(exprs_answers_str, 'text/html')

        return problemTemplate

    def _problem_all_expressions_n1_n2(self, *args, **kwargs):
        implies = symbols(u'\U000021D2')
        n1 = random.randint(1, 10)
        n2 = random.randint(1, 10)

        bve = BivariateExpressions(n1, n2)

        expr_and_result_labels = bve.get_expr_and_result_labels()
        #exprs_solns_str = "\n\n".join(expr_and_result_labels)
        exprs_solns_str = [f"<b>Solution {i+1}.</b>\n{x}"
                           for i, x in enumerate(expr_and_result_labels)]
        exprs_solns_str = "\n\n".join(exprs_solns_str)

        answers = bve.get_exprs(regex = True)
        #exprs_answers_str = "\n\n".join(answers)
        exprs_answers_str = [f"<b>Answer {i+1}.</b>\n{x}"
                             for i, x in enumerate(answers)]
        exprs_answers_str = "\n\n".join(exprs_answers_str)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        statement = f"""
        Write all possible expressions and their values using {n1} and {n2}.
        You can use positive or negative if you want. Use +, -, /, power and log operators.
        """
        problemTemplate.add_problem(statement, 'text/html')

        problemTemplate.add_solution(exprs_solns_str, 'text/html')
        problemTemplate.add_answer(exprs_answers_str, 'text/html')

        return problemTemplate

    def _problem_abs(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        n1 = random.choice([
            random.randint(-10, 10),
            Rational(random.randint(-10, 10), random.randint(-10, 10)),
            random.choice([0.1, 0.2, 0.25, 0.5,]),
            random.choice([0.1, 0.2, 0.25, 0.5,]) + random.randint(-10, 10)
            ]) * random.choice([1, -1])

        problem_s = f"""
        What is absolute value of $\\displaystyle {latex(n1)}$?
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        In absolute value, we disregard the negative sign, if it is there.
        $\\displaystyle \\left|  \\right|$ is symbol of absolute value.

        $\\displaystyle \\text{{abs}} \\left( {latex(n1)} \\right)$

        $\\displaystyle = \\left| {latex(n1)} \\right|$

        $\\displaystyle = {latex(abs(n1))}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(abs(n1))}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate

    def _problem_abs_advanced(self, *args, **kwargs):
        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        count = 2
        nums = []
        while len(nums) < count:
            n = random.choice([
                random.randint(-10, 10),
                Rational(random.randint(-10, 10), random.randint(1, 10)),
                random.choice([0.1, 0.2, 0.25, 0.5,]),
                random.choice([0.1, 0.2, 0.25, 0.5,]) + random.randint(-10, 10)
                ]) * random.choice([1, -1])

            nums.append(n)
            pass

        n1, n2 = nums

        op = random.choice([0, 1, 2, 3, 4])

        num_eval = None
        if op == 1:
            num = UnevaluatedExpr(n1) - UnevaluatedExpr(n2)
        elif op == 2:
            num = UnevaluatedExpr(n1) * UnevaluatedExpr(n2)
        elif op == 3:
            if n2 == 0:
                n2 = random.randint(2, 9) * random.choice([1, -1])
            num = UnevaluatedExpr(n1) / UnevaluatedExpr(n2)
        elif op == 3:
            num = UnevaluatedExpr(n1) + UnevaluatedExpr(n2)
        else:
            if n1 == 0 and n2 <= 0:
                n2 = random.randint(2, 9)
            elif n1 < 0:
                n1 = random.randint(2, 9) * random.choice([1, -1])
                n2 = random.randint(2, 9)

            num = UnevaluatedExpr(n1) ** UnevaluatedExpr(n2)
            pass


        if op in [1, 2, 3, 4]:
            num_eval = simplify(num)
            abs_num_eval = abs(num_eval)
        else:
            if n1 >= 0:
                abs_num_eval = num
            elif n2 % 2 == 0:
                abs_num_eval = num
            else:
                num_eval = simplify(num)
                abs_num_eval = abs(num_eval)


        problem_s = f"""
        What is absolute value of $\\displaystyle {latex(num)}$?
        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        In absolute value, we disregard the negative sign, if it is there.
        $\\displaystyle \\left|  \\right|$ is symbol of absolute value.

        $\\displaystyle \\text{{abs}} \\left( {latex(num)} \\right)$

        $\\displaystyle = \\left| {latex(num)} \\right|$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        if not num_eval is None:
            soln_s = f"""
            $\\displaystyle = \\left| {latex(num_eval)} \\right|$
            """
            problemTemplate.add_solution(soln_s.strip(), 'text/html')

        soln_s = f"""
        $\\displaystyle = {latex(abs_num_eval)}$
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {latex(abs_num_eval)}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_make_similar(self, *args, **kwargs):
        count = random.randint(3, 5)
        fracs = []

        while len(fracs) < count:
            item = Rational(random.randint(1, 9) * 10 ** random.randint(0, 2),
                            random.randint(1, 9) * 10 ** random.randint(0, 2))
            fracs.append(item)
            pass

        fracs_latex = [f"{latex(x)}" for x in fracs]
        fracs_latex_str = ",\\;".join(fracs_latex)

        fracs_denoms = [x.q for x in fracs]
        lcm = MathUtil.lcm(*fracs_denoms)

        comm_denm_fracs_latex = [latex_fraction(f"{x.p} \\cdot {lcm // x.q}",
                                                f"{x.q} \\cdot {lcm // x.q}")
                                 for x in fracs]
        comm_denm_fracs_latex_str = ",\\;".join(comm_denm_fracs_latex)


        comm_denm_eval_fracs_latex = [latex_fraction(f"{x.p * lcm // x.q}", f"{lcm}")
                                      for x in fracs]
        comm_denm_eval_fracs_latex_str = ",\\;".join(comm_denm_eval_fracs_latex)

        deci_nums = [toIntOrFloat(float(x), random.randint(1, 5)) for x in fracs]
        deci_nums_latex = [f"{latex(x)}" for x in deci_nums]
        deci_nums_latex_str = ",\\;".join(deci_nums_latex)

        from xv.util import make_floats_similar

        deci_similar_html = make_floats_similar(deci_nums, html = True)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        problem_s = f"""
        Make the following similar.

        $\\displaystyle {fracs_latex_str}$

        $\\displaystyle {deci_nums_latex_str}$



        """
        problemTemplate.add_problem(problem_s.strip(), 'text/html')

        soln_s = f"""
        <h4>Make rational numbers similar:</h4>
        $\\displaystyle {fracs_latex_str}$

        The LCM of denominators  $\\displaystyle {latex(fracs_denoms)} = {latex(lcm)}$.
        Therefore, we will make all denominators equal to $\\displaystyle {latex(lcm)}$.

        $\\displaystyle = {comm_denm_fracs_latex_str}$

        $\\displaystyle = {comm_denm_eval_fracs_latex_str}$

        <h4>Make decimal numbers similar:</h4>
        $\\displaystyle {deci_nums_latex_str}$

        If number has no deciaml, place decimal to the end of the number.
        Write decimal at same verticle position and fill zeros to left and right empty space.

        {deci_similar_html}

        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        $\\displaystyle {comm_denm_eval_fracs_latex_str}$
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate


    def _problem_mixed_operations(self, *args, **kwargs):

        ao_helper = self.base_helper.get_arithmetic_helper().get_arithmetic_operation_helper()
        result = ao_helper.get_problem_mixed_operations(**kwargs)

        problemTemplate = KProblemTemplate()
        problemTemplate.problem_type = kwargs.get('problem_type')

        prob_s = f"""
        {result['prob_s']}
        """
        problemTemplate.add_problem(prob_s.strip(), 'text/html')

        soln_s = f"""
        {result['soln_s']}
        """
        problemTemplate.add_solution(soln_s.strip(), 'text/html')

        answer_s = f"""
        {result['answer_s']}
        """
        problemTemplate.add_answer(answer_s.strip(), 'text/html')

        return problemTemplate
