'''
Created on 20-Jan-2022

@author: bthakur
'''

import inspect
import traceback
import random
import numpy as np
from sympy import (latex, Symbol, symbols,
                   sqrt, nsimplify, simplify,
                   UnevaluatedExpr as ueval,
                   )

from xv.util import toIntOrFloat, listAttr
from xv.km.storeddata import BaseStoredQuestions

# _inequality_stored_questions
# InequalityStoredQuestions

class InequalityStoredQuestions(BaseStoredQuestions):
    _QUESTION_KEYWORDS = None
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        pass

    def get_q_indexes(self):
        q_indexes_dict = self._get_q_indexes_dict()
        q_indexes = list(q_indexes_dict.values()) 
        return q_indexes
        pass

    def _get_q_indexes_dict(self):
        q_indexes_dict = {}
        
        prob_s = rf"""
        Show that
        $$
        1 \cdot 3 \cdot 5 \cdots(2 n-1) \leq n^{{n}}
        $$
        """
        q_indexes_dict['am_gm_inequality_type_1'] = prob_s.strip()

        
        prob_s = rf"""
        Show that if $a, b, c$ are all positive, then
        $$
        (a+b)(b+c)(a+c) \geq 8 a b c
        $$
        """
        q_indexes_dict['am_gm_inequality_type_2'] = prob_s.strip()


        prob_s = rf"""
        Find positive numbers $n$ and $a_{{1}}, a_{{2}}, \ldots, a_{{n}}$ such that $a_{{1}}+\cdots+a_{{n}}$ $=1000$ and the product $a_{{1}} a_{{2}} \cdots a_{{n}}$ is as large as possible.
        """
        q_indexes_dict['maximize_pos_nums'] = prob_s.strip()

        
        return q_indexes_dict
        pass
    
    
    def get_question_am_gm_inequality_type_1(self):
        
        keywords = [
            'inequality', 'AM-GM inequality', 'AM', 'GM',
            'am_gm_inequality_type_1',
            ]
        
        q_key = 'am_gm_inequality_type_1'
        prob_s = self._get_q_indexes_dict()[q_key]
        
        soln_s = rf"""
    
        By the AM-GM inequality, we have that
        
        $$\displaystyle
        \sqrt[n]{{1 \cdot 3 \cdot 5 \cdots(2 n-1)}} \leq \frac{{1+3+\cdots+(2 n-1)}}{{n}}
        $$
        
        $$
        \text {{as}}\quad 1+3+\cdots+(2 n-1)=n^{{2}}
        $$
        
        $$
        \Rightarrow \sqrt[n]{{1 \cdot 3 \cdot 5 \cdots(2 n-1)}} \leq \frac{{n^{{2}}}}{{n}}=n
        $$
        
        $$
        \Rightarrow 1 \cdot 3 \cdot 5 \cdots(2 n-1) \leq n^{{n}}
        $$
                
        """
        
        answer_s = rf"""
        $$
        1 \cdot 3 \cdot 5 \cdots(2 n-1) \leq n^{{n}}
        $$
                
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    
    def get_question_am_gm_inequality_type_2(self):
        
        keywords = [
            'inequality', 'AM-GM inequality', 'AM', 'GM', 'putnam', 'abc',
            'am_gm_inequality_type_2',
            ]
        
        q_key = 'am_gm_inequality_type_2'
        prob_s = self._get_q_indexes_dict()[q_key]
        
        soln_s = rf"""
        
        Using AM-GM, we get that
        $$
        \begin{{aligned}}
        \frac{{a+b}}{{2}} & \geq \sqrt{{a b}} \\
        \\
        \Rightarrow a+b & \geq 2 \sqrt{{a b}}
        \end{{aligned}}
        $$
        Similarly,
        $$
        \begin{{aligned}}
        &b+c \geq 2 \sqrt{{b c}} \\
        &a+c \geq 2 \sqrt{{a c}}
        \end{{aligned}}
        $$
        As all numbers are positive, inequality holds for
        
        $$
        \begin{{aligned}}
        (a+b)(b+c)(a+c) & \geq(2 \sqrt{{a b}})(2 \sqrt{{b c}})(2 \sqrt{{a c}}) \\
        \\
        &=8 \sqrt{{a b \cdot b c \cdot a c}} \\
        \\
        &=8 \sqrt{{a^{{2}} b^{{2}} c^{{2}}}} \\
        \end{{aligned}}
        $$
        
        $$
        \Rightarrow (a+b)(b+c)(a+c) \geq 8 a b c
        $$
        

        """
        
        answer_s = rf"""
        $$
        (a+b)(b+c)(a+c) \geq 8 a b c
        $$
        """

        result = {
            'keywords': keywords,
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        return result
        pass
    
    def get_question_maximize_pos_nums(self):
        
        keywords = [
            'assorted', 'maximize', 'positive numbers',
            ]

        q_key = 'maximize_pos_nums'
        prob_s = self._get_q_indexes_dict()[q_key]
        
        soln_s = rf"""
        Let us find simple cases with sum as smaller number and the best solution.
        At sum = 2, 1 + 1 = 2, max product 1 * 1 = 1
        At sum = 3, 2 + 1 = 2, max product 2 * 1 = 2
        At sum = 4, 2 + 2 = 4, max product 2 * 2 = 4
        At sum = 5, 3 + 2 = 5, max product 3 * 2 = 6
        At sum = 6, 3 + 3 = 6, max product 3 * 3 = 9
        At sum = 7, 3 + 2 + 2 = 7, max product 3 * 2 * 2 = 12
        At sum = 8, 3 + 3 + 2 = 8, max product 3 * 3 * 2 = 18
        At sum = 9, 3 + 3 + 3 = 9, max product 3 * 3 * 3 = 27
        At sum = 10, 3 + 3 + 2 + 2 = 10, max product 3 * 3 * 2 * 2 = 36
        At sum = 11, 3 + 3 + 3 + 2 = 11, max product 3 * 3 * 3 * 2 = 54
        At sum = 12, 3 + 3 + 3 + 3 = 12, max product 3 * 3 * 3 * 3 = 81
        At sum = 13, 3 + 3 + 3 + 2 + 2 = 13, max product 3 * 3 * 3 * 2 * 2 = 108
        At sum = 14, 3 + 3 + 3 + 3 + 2 = 10, max product 3 * 3 * 3 * 3 * 2 = 162
        ...
        
        At sum = 1000, 3 + 3 + ... + 3 + 3 + 2 + 2, max product $3^{{332}} \times 2^{{2}}$
        """
        
        answer_s = rf"""
        $3^{{332}} \times 2^{{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_numbers_with_roots(self):
        
        keywords = [
            'assorted', 'compare', 'numbers_with_roots',
            ]
        
        n1 = random.randint(15, 20)
        n3 = sqrt(ueval(random.randint(5, 10) ** 2 - random.randint(1, 3) ))
        n3_eval = float(simplify(n3))
        
        n4 = int(n1 - n3_eval)
        n4 = nsimplify(n4 * random.randint(95, 105) / 100)
        
        n5 = n1 - n4
        
        n5sqr = n5 ** 2
        
        n6 = n5sqr * n5sqr.q
        n7 = simplify(n3 ** 2 * n5sqr.q)

        if n6 == n7:
            op = "="
        elif n6 > n7:
            op = ">"
        elif n6 < n7:
            op = "<"
        else:
            op = "?"
        
        prob_s = rf"""
        Find 
        
        $\displaystyle 
        {n1} - {{{latex(n3)}}} 
        \qquad ? \qquad 
        {{{latex(n4)}}}
        $
                                
        """

        
        soln_s = rf"""
        
        $\displaystyle 
        {n1} - {{{latex(n3)}}} 
        \qquad ? \qquad 
        {{{latex(n4)}}}
        $
        
        $\displaystyle \implies 
        {n1} - {{{latex(n3)}}} + {{{latex(n3)}}} - {{{latex(n4)}}}
        \qquad ? \qquad 
        {{{latex(n4)}}} + {{{latex(n3)}}} - {{{latex(n4)}}}
        $
        
        $\displaystyle \implies  
        {n1} - {{{latex(n4)}}} 
        \qquad ? \qquad  
        {{{latex(n3)}}}
        $
        
        $\displaystyle \implies  
        {{{latex(n5)}}} 
        \qquad ? \qquad  
        {{{latex(n3)}}}
        $
        
        As both sides are positive, we can square them without changing inequality status:
        
        $\displaystyle \implies  
        {{{latex(n5sqr)}}} 
        \qquad ? \qquad  
        {{{latex(n3 ** 2)}}}
        $
        
        $\displaystyle \implies  
        {{{latex(n5sqr)} * {latex(n5sqr.q)}}} 
        \qquad ? \qquad  
        {{{latex(n3 ** 2)} * {latex(n5sqr.q)}}}
        $
        
        $\displaystyle \implies  
        {{{latex(n6)}}} 
        \qquad ? \qquad  
        {{{latex(n7)}}}
        $
        
        $\displaystyle \implies  
        {{{latex(n6)}}} 
        \qquad {op} \qquad  
        {{{latex(n7)}}}
        $
        
        
        $\displaystyle \implies
        {n1} - {{{latex(n3)}}} 
        \qquad {op} \qquad 
        {{{latex(n4)}}}
        $
        
        """
        
        answer_s = rf"""
        $\displaystyle 
        {n1} - {{{latex(n3)}}} 
        \qquad {op} \qquad 
        {{{latex(n4)}}}
        $
        """

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