'''
Created on 20-Jan-2022

@author: bthakur
'''

import inspect
import traceback
import random
import numpy as np
from sympy import (latex, Symbol, symbols,
                   Eq, Rational,
                   UnevaluatedExpr as ueval,
                   )

from xv.util import toIntOrFloat, listAttr
from xv.km.storeddata import BaseStoredQuestions
from xv.km import CustomLogarithm as Log
from xv.km.util import latex_log, latex_fraction, latex_exponent

# EssentialTechniquesStoredQuestions

class EssentialTechniquesStoredQuestions(BaseStoredQuestions):
    _QUESTION_KEYWORDS = None
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass
    
    
    def get_question_example_1(self):
        keywords = [
            'example 1',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Shew, without using a calculator, that $6-\sqrt{{35}}<\frac{{1}}{{10}}$.
        """
        
        soln_s = rf"""
        Assume that $6-\sqrt{{35}} \geq \frac{{1}}{{10}}$. Then $6-\frac{{1}}{{10}} \geq \sqrt{{35}}$ or $59 \geq 10 \sqrt{{35}}$. Squaring both sides we obtain $3481 \geq 3500$, which is clearly nonsense. Thus it must be the case that $6-\sqrt{{35}}<\frac{{1}}{{10}}$.

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        Assume that $6-\sqrt{{35}} \geq \frac{{1}}{{10}}$. Then $6-\frac{{1}}{{10}} \geq \sqrt{{35}}$ or $59 \geq 10 \sqrt{{35}}$. Squaring both sides we obtain $3481 \geq 3500$, which is clearly nonsense. Thus it must be the case that $6-\sqrt{{35}}<\frac{{1}}{{10}}$.
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_2(self):
        keywords = [
            'example 2',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Let $a_{{1}}, a_{{2}}, \ldots, a_{{n}}$ be an arbitrary permutation of the numbers $1,2, \ldots, n$, where $n$ is and number. Prove that the product
        $\left(a_{{1}}-1\right)\left(a_{{2}}-2\right) \cdots\left(a_{{n}}-n\right)$
        is even.
        """
        
        soln_s = rf"""
        First observe that the sum of an odd number of odd integers is odd. It is enough to prove that some difference $a_{{k}}-k$ is even. Assume contrariwise that all the differences $a_{{k}}-k$ are odd. Clearly
        $S=\left(a_{{1}}-1\right)+\left(a_{{2}}-2\right)+\cdots+\left(a_{{n}}-n\right)=0,$
        since the $a_{{k}}$ 's are a reordering of $1,2, \ldots, n . S$ is an odd number of summands of odd integers adding to the even integer 0 . This is impossible. Our initial assumption that all the $a_{{k}}-k$ are odd is wrong, so one of these is even and hence the product is even.
        
        {hint_s.strip()}
        """
        
        answer_s = rf"""
        First observe that the sum of an odd number of odd integers is odd. It is enough to prove that some difference $a_{{k}}-k$ is even. Assume contrariwise that all the differences $a_{{k}}-k$ are odd. Clearly
        $S=\left(a_{{1}}-1\right)+\left(a_{{2}}-2\right)+\cdots+\left(a_{{n}}-n\right)=0,$
        since the $a_{{k}}$ 's are a reordering of $1,2, \ldots, n . S$ is an odd number of summands of odd integers adding to the even integer 0 . This is impossible. Our initial assumption that all the $a_{{k}}-k$ are odd is wrong, so one of these is even and hence the product is even.
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_3(self):
        keywords = [
            'example 3',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Prove that $\sqrt{{2}}$ is irrational.

        """
        
        soln_s = rf"""
        For this proof, we will accept as fact that any positive integer greater than 1 can be factorised uniquely as the product of primes (up to the order of the factors).

        Assume that $\sqrt{{2}}=\frac{{a}}{{b}}$, with positive integers $a, b$. This yields $2 b^{{2}}=a^{{2}}$. Now both $a^{{2}}$ and $b^{{2}}$ have an even number of prime factors. So $2 b^{{2}}$ has an odd numbers of primes in its factorisation and $a^{{2}}$ has an even number of primes in its factorisation. This is a contradiction.

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        For this proof, we will accept as fact that any positive integer greater than 1 can be factorised uniquely as the product of primes (up to the order of the factors).

        Assume that $\sqrt{{2}}=\frac{{a}}{{b}}$, with positive integers $a, b$. This yields $2 b^{{2}}=a^{{2}}$. Now both $a^{{2}}$ and $b^{{2}}$ have an even number of prime factors. So $2 b^{{2}}$ has an odd numbers of primes in its factorisation and $a^{{2}}$ has an even number of primes in its factorisation. This is a contradiction.
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_4(self):
        keywords = [
            'example 4',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Let $a, b$ be real numbers and assume that for all numbers $\varepsilon>0$ the following inequality holds:
        $a<b+\varepsilon$
        Prove that $a \leq b$.

        """
        
        soln_s = rf"""
        Assume contrariwise that $a>b$. Hence $\displaystyle\frac{{a-b}}{{2}}>0$. Since the inequality $a<b+\varepsilon$ holds for every $\varepsilon>0$ in particular it holds for $\displaystyle \varepsilon=\frac{{a-b}}{{2}}$. This implies that
        $\displaystyle a<b+\frac{{a-b}}{{2}} \text {{ or }} a<b .$
        Thus starting with the assumption that $a>b$ we reach the incompatible conclusion that $a<b$. The original assumption must be wrong. We therefore conclude that $a \leq b$.

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        Assume contrariwise that $a>b$. Hence $\displaystyle\frac{{a-b}}{{2}}>0$. Since the inequality $a<b+\varepsilon$ holds for every $\varepsilon>0$ in particular it holds for $\displaystyle \varepsilon=\frac{{a-b}}{{2}}$. This implies that
        $\displaystyle a<b+\frac{{a-b}}{{2}} \text {{ or }} a<b .$
        Thus starting with the assumption that $a>b$ we reach the incompatible conclusion that $a<b$. The original assumption must be wrong. We therefore conclude that $a \leq b$.
        
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_5(self):
        keywords = [
            'example 5',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        (Euclid) Shew that there are infinitely many prime numbers.

        """
        
        soln_s = rf"""
        We need to assume for this proof that any integer greater than 1 is either a prime or a product of primes. The following beautiful proof goes back to Euclid. Assume that $\left\{{p_{{1}}, p_{{2}}, \ldots, p_{{n}}\right\}}$ is a list that exhausts all the primes. Consider the number
        $N=p_{{1}} p_{{2}} \cdots p_{{n}}+1$
        This is a positive integer, clearly greater than 1 . Observe that none of the primes on the list $\left\{{p_{{1}}, p_{{2}}, \ldots, p_{{n}}\right\}}$ divides $N$, since division by any of these primes leaves a remainder of 1 . Since $N$ is larger than any of the primes on this list, it is either a prime or divisible by a prime outside this list. Thus we have shewn that the assumption that any finite list of primes leads to the existence of a prime outside this list. This implies that the number of primes is infinite.

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        We need to assume for this proof that any integer greater than 1 is either a prime or a product of primes. The following beautiful proof goes back to Euclid. Assume that $\left\{{p_{{1}}, p_{{2}}, \ldots, p_{{n}}\right\}}$ is a list that exhausts all the primes. Consider the number
        $N=p_{{1}} p_{{2}} \cdots p_{{n}}+1$
        This is a positive integer, clearly greater than 1 . Observe that none of the primes on the list $\left\{{p_{{1}}, p_{{2}}, \ldots, p_{{n}}\right\}}$ divides $N$, since division by any of these primes leaves a remainder of 1 . Since $N$ is larger than any of the primes on this list, it is either a prime or divisible by a prime outside this list. Thus we have shewn that the assumption that any finite list of primes leads to the existence of a prime outside this list. This implies that the number of primes is infinite.

        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_6(self):
        keywords = [
            'example 6',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Let $n>1$ be a composite integer. Prove that $n$ has a prime factor $p \leq \sqrt{{n}}$.

        """
        
        soln_s = rf"""
        Since $n$ is composite, $n$ can be written as $n=a b$ where both $a>1, b>1$ are integers. Now, if both $a>\sqrt{{n}}$ and $b>\sqrt{{n}}$ then $n=a b>\sqrt{{n}} \sqrt{{n}}=n$, a contradiction. Thus one of these factors must be $\leq \sqrt{{n}}$ and $a$ fortiori it must have a prime factor $\leq \sqrt{{n}}$

        The result in example 6 can be used to test for primality. For example, to shew that 101 is prime, we compute $\lfloor\sqrt{{101}} \|=10$. By the preceding problem, either 101 is prime or it is divisible by $2,3,5$, or 7 (the primes smaller than 10 ). Since neither of these primes divides 101 , we conclude that 101 is prime.

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        Since $n$ is composite, $n$ can be written as $n=a b$ where both $a>1, b>1$ are integers. Now, if both $a>\sqrt{{n}}$ and $b>\sqrt{{n}}$ then $n=a b>\sqrt{{n}} \sqrt{{n}}=n$, a contradiction. Thus one of these factors must be $\leq \sqrt{{n}}$ and $a$ fortiori it must have a prime factor $\leq \sqrt{{n}}$

        The result in example 6 can be used to test for primality. For example, to shew that 101 is prime, we compute $\lfloor\sqrt{{101}} \|=10$. By the preceding problem, either 101 is prime or it is divisible by $2,3,5$, or 7 (the primes smaller than 10 ). Since neither of these primes divides 101 , we conclude that 101 is prime.

        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass

    def get_question_example_7(self):
        keywords = [
            'example 7',
            ]
        
        
        hint_s = rf"""
        <b>See the following managers for more detailed explanation:</b>
        
        """
        
        prob_s = rf"""
        Prove that a sum of two squares of integers leaves remainder 0,1 or 2 when divided by $4 .$

        """
        
        soln_s = rf"""
        An integer is either even (of the form $2 k$ ) or odd (of the form $2 k+1$ ). We have
        $\begin{{array}}{{ll}} (2 k)^{{2}} & =4\left(k^{{2}}\right) \\ (2 k+1)^{{2}} & =4\left(k^{{2}}+k\right)+1 \end{{array}}$
        Thus squares leave remainder 0 or 1 when divided by 4 and hence their sum leave remainder 0,1 , or 2 .

        {hint_s.strip()}
        """
        
        answer_s = rf"""
        An integer is either even (of the form $2 k$ ) or odd (of the form $2 k+1$ ). We have
        $\begin{{array}}{{ll}} (2 k)^{{2}} & =4\left(k^{{2}}\right) \\ (2 k+1)^{{2}} & =4\left(k^{{2}}+k\right)+1 \end{{array}}$
        Thus squares leave remainder 0 or 1 when divided by 4 and hence their sum leave remainder 0,1 , or 2 .

        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass


    def get_question_SAMPLE(self):
        keywords = [
            'grade7',
            'grade 7',
            ]
        
        hint_s = rf"""
        <b>:</b>
        
        """
        
        prob_s = rf"""

        """
        
        soln_s = rf"""

        
        {hint_s.strip()}

        """
        
        answer_s = rf"""
        
        
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    
    pass
#class EssentialTechniquesStoredQuestions:
