'''
Created on 21-Aug-2024

@author: bthakur
'''
import random
import inspect
import traceback

import numpy as np
import sympy as sp

from sympy import (symbols, Symbol, pi, latex, sympify,
                   Rational, Derivative, simplify,
                   UnevaluatedExpr as ueval
                   )
from xv.km.util import latex_fraction, wrap_in_latex
from xv.util import number_to_nth, list_to_str, toIntOrFloat


from  xv.util import UtilClass

# DivisibilityHelper
# _divisibility_helper
 

class DivisibilityHelper(UtilClass):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self._precision = 6
        pass
    
    def get_problem_traditional_division(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
        
        
        divisor = random.randint(1, 9) * random.choice([2, 8])
        dividend1 = divisor * random.randint(1, 9) * 10 ** random.randint(1, 2)
        dividend2 = divisor * random.randint(1, 9) * 10 ** random.randint(5, 6)
        dividend3 = divisor * random.randint(1, 9) * 10 ** random.randint(8, 10)
        
        dividend = dividend1 + dividend2 + dividend3
        if random.choice([True, True, False]):
            dividend_precision = random.randint(1, len(str(dividend)))
            dividend = dividend * 10 ** -dividend_precision
            dividend = round(dividend, dividend_precision)
        else:
            dividend_precision = 1
            dividend = dividend * 10 ** random.randint(1, 3)
            
        divisor_precision = random.randint(1, 4)
        divisor = divisor * 10 ** ( divisor_precision * random.choice([1, -1]))
        divisor = toIntOrFloat(divisor, divisor_precision)
        if divisor > 100:
            divisor = divisor + random.choice([0, 1, 2])
        
        quotient = toIntOrFloat(dividend / divisor, 
                                dividend_precision + divisor_precision)
        
        
        #the division process
        divisor_str = str(divisor)
        if "." in divisor_str:
            decimal_points = len(divisor_str.split('.')[-1])
            mod_dividend = toIntOrFloat(dividend * 10 ** decimal_points, 
                                        dividend_precision)
            mod_divisor = int(divisor_str.replace(".", ""))
        else:
            mod_dividend = dividend
            mod_divisor = divisor

        dividend_str = str(mod_dividend)
        if "." in dividend_str:
            dividend_int, dividend_decimals = [x.strip()
                                               for x in dividend_str.split(".")]
            dividend_int = int(dividend_int)
        else:
            dividend_int, dividend_decimals = mod_dividend, ""



        mod_quotient = toIntOrFloat(mod_dividend / mod_divisor, 
                                    dividend_precision + divisor_precision)
        
        mod_quotient_str = str(mod_quotient)
        if "." in mod_quotient_str:
            mod_quotient_decimal_points = len(mod_quotient_str.split('.')[-1])
            temp_dec = mod_quotient_decimal_points - len(dividend_decimals) 
            if temp_dec >= 0:
                dividend_decimals = dividend_decimals + "0" * (temp_dec + 1)
        
        dividend_str = f"{dividend_int}.{dividend_decimals}"
        

        prob_s = f"""
        Divide {dividend} with {divisor}
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        {dividend} / {divisor}
        """
        soln_stmts.append(soln_stmt.strip())

        
        if divisor != mod_divisor:
            soln_stmt = f"""
            = {mod_dividend} / {mod_divisor}
            """
            soln_stmts.append(soln_stmt.strip())

    
        soln_stmt = f"""
        = {dividend_str} / {mod_divisor}
        """
        soln_stmts.append(soln_stmt.strip())

        
        item_dividend = ""
        calc_quotient = ""

        
        soln_items = []
        for i, n in enumerate(dividend_str):
            if n == ".":
                calc_quotient = calc_quotient + "."
                
                soln_item = f"""
                <tr>
                <td></td>
                <td>{calc_quotient[:-1]}<b class = "large_font">{calc_quotient[-1]}</b></td>
                <td></td>
                <td>Put decimal in quotient, {dividend_str[:i]}<b class = "large_font">{dividend_str[i]}</b>{dividend_str[i+1:]}</td>
                <td></td>
                </tr>
                """
                soln_items.append(soln_item.strip())
                
                continue
            
            item_dividend = item_dividend + n

            item_mul = int(item_dividend) // mod_divisor
            calc_quotient = calc_quotient + str(item_mul)
            item_rem = int(item_dividend) % mod_divisor
            
            soln_item = f"""
            <tr>
            <td max-width: 200px ></td>
            <td><u>{calc_quotient[:-1]}<b class = "large_font">{calc_quotient[-1]}</b></u></td>
            <td></td>
            <td></td>
            <td></td>
            </tr>
            """
            soln_items.append(soln_item.strip())
            
            soln_item = f"""
            <tr>
            <td>{mod_divisor} )</td>
            <td>{item_dividend[:-1]}<b class = "large_font_blue">{item_dividend[-1]}</b></td>
            <td>&nbsp;&nbsp;</td>
            <td>bringing {n} down from {dividend_str[:i]}<b class = "large_font_blue">{dividend_str[i]}</b>{dividend_str[i+1:]}</td>
            <td></td>
            </tr>
            """
            soln_items.append(soln_item.strip())
            
            soln_item = f"""
            <tr>
            <td></td>
            <td><u>-{item_mul * mod_divisor}</u></td>
            <td>&nbsp;&nbsp;</td>
            <td><b class = "large_font">{item_mul}</b> * {mod_divisor} = {item_mul * mod_divisor}</td>
            <td></td>
            </tr>
            """
            soln_items.append(soln_item.strip())
            
            soln_item = f"""
            <tr>
            <td></td>
            <td>{item_rem}</td>
            <td>&nbsp;&nbsp;</td>
            <td></td>
            <td></td>
            </tr>
            """
            soln_items.append(soln_item.strip())
            
            soln_item = f"""
            <tr>
            <td></td>
            <td></td>
            <td>&nbsp;&nbsp;</td>
            <td></td>
            <td></td>
            </tr>
            """
            soln_items.append(soln_item.strip())
            
            
            item_dividend = str(item_rem)
            pass

        soln_items_s = "".join(soln_items)

        soln_stmt = f"""
        <style>
        .large_font{{
        font-size: 1.2em;
        color: red;
        }}
        .large_font_blue{{
        font-size: 1.2em;
        color: blue;
        }}
        </style>
        """
        soln_stmts.append(soln_stmt.replace("\n", "").strip())
        
        
        soln_stmt = f"""<table class = "div_mgr_table">{soln_items_s}</table>"""
        soln_stmts.append(soln_stmt.replace("\n", "").strip())
        
        
        soln_stmt = f"""
        Hence, {dividend} / {divisor} = {mod_quotient}
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_s = "\n\n".join(soln_stmts)
        
        answer_s = f"""
        {mod_quotient}
        """
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        
        return result
        pass


    def get_problem_divisible_by_multiples_of_10(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        

        dividend = random.randint(0, 1000) * 10 ** random.randint(0, 5) 
        divisor = 10 ** random.randint(1, 5) 
        divisor_zeros_len = len(str(divisor)) - 1
        isDivisible = round(dividend / divisor, divisor_zeros_len) == dividend // divisor

        dividend_rev = list(str(dividend))[::-1]

        dividend_zeros_len = 0
        for item in dividend_rev:
            if not item == "0":
                break
            dividend_zeros_len = dividend_zeros_len + 1
            pass

        lastDigits = dividend % divisor
        if len(str(dividend)) >= divisor_zeros_len:
            lastDigits_str = str(dividend)[-divisor_zeros_len:]
        else:
            lastDigits_str = str(dividend)
            
        isDivisible_lastDigit = round(lastDigits / divisor, divisor_zeros_len) == lastDigits // divisor
        
        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        If number of trailing zeros in dividend is 
        more than or equal to trailing zeros in divisor, 
        the dividend is divisible by the divisor.
        <br/>
        <br/>
        Number of trailing zeros in dividend {dividend} = {dividend_zeros_len}
        <br/>
        <br/>
        Number of trailing zeros in divisor {divisor} = {divisor_zeros_len}
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        
        if dividend_zeros_len >= divisor_zeros_len:
            soln_stmt = f"""
            $ \\displaystyle 
            
            \\begin {{aligned}}
            
            \\text {{ As }} & \\qquad {dividend_zeros_len} >= {divisor_zeros_len}
            \\\\ \\\\
            
            & \\implies \\text{{ Number of trailing zeros in dividend {dividend} }}
            >= \\text{{ Number of trailing zeros in divisor {divisor} }}
            \\\\ \\\\
            
            & \\implies \\text{{ {dividend} is divisible by {divisor}. }}
            
            \\end {{aligned}}
            $
            """
            soln_stmts.append(soln_stmt.strip())
        else:
            soln_stmt = f"""
            $ \\displaystyle 
            
            \\begin {{aligned}}
            
            \\text {{ As }} & \\qquad {dividend_zeros_len} < {divisor_zeros_len}
            \\\\ \\\\
            
            & \\implies \\text{{ Number of trailing zeros in dividend {dividend} }}
            < \\text{{ Number of trailing zeros in divisor {divisor} }}
            \\\\ \\\\
            
            & \\implies \\text{{ {dividend} is not divisible by {divisor}. }}
            
            \\end {{aligned}}
            $
            """
            soln_stmts.append(soln_stmt.replace("\n", " ").strip())
            pass
        
        
        answer_s = f"""
        {isDivisible}
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
                
        result = {
            'prob_s': prob_s.replace("\n", " ").strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            'isDivisible': isDivisible,
            }
        
        return result
        pass

    def get_problem_divisible_by_2_5(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
        divisor = kwargs.get('divisor', None)
        dividend = kwargs.get('dividend', None)
        
        if divisor is None:
            divisor = random.choice([2, 5])
            
        if dividend is None:
            dividend = random.choice([random.randint(0, 1000000),
                                      divisor * random.randint(0, 100000)])
        

        isDivisible = round(dividend / divisor, self._precision) == dividend // divisor
        
        lastDigit = dividend % 10
        isDivisible_lastDigit = round(lastDigit / divisor, self._precision) == lastDigit // divisor
        
        
        
        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        Take the last digit of dividend {dividend} and if it is divisible by {divisor}, 
        the number is also divisible by {divisor}.
        <br/>
        <br/>
        The last digit in {dividend} is {lastDigit}.
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        if isDivisible != isDivisible_lastDigit:
            soln_stmt = f"""
            <h1>ERROR:</h1>
            """
            soln_stmts.append(soln_stmt.strip())
    
        
        if isDivisible_lastDigit:
            soln_stmt = f"""
            {lastDigit} is divisible by divisor {divisor}. 
            Hence, {dividend} is also divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass
        else:
            soln_stmt = f"""
            {lastDigit} is not divisible by divisor {divisor}. 
            Hence, {dividend} is also not divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass
        


        answer_s = f"""
        {isDivisible_lastDigit}
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            'isDivisible': isDivisible,
            }
        
        return result
        pass


    def get_problem_divisible_by_3_9(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
 
        divisor = kwargs.get('divisor', None)
        dividend = kwargs.get('dividend', None)
        
        if divisor is None:
            divisor = random.choice([3, 9])
            
        if dividend is None:
            dividend = random.choice([random.randint(0, 1000000),
                                      divisor * random.randint(0, 100000)])

        
        
        isDivisible = round(dividend / divisor, self._precision) == dividend // divisor
        
        sumOfDigits, sumOfDigits_str = self.sum_digits(dividend)
        isDivisible_sumOfDigits = round(sumOfDigits / divisor, self._precision) == sumOfDigits // divisor
       
        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        Take the sum of digits of dividend {dividend}. 
        If the sum is divisible by {divisor}, 
        the number is also divisible by {divisor}
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        soln_stmt = f"""
        The sum of digits of {dividend}
        = {sumOfDigits_str} 
        = {sumOfDigits}
        """
        soln_stmts.append(soln_stmt.strip())

        while sumOfDigits > 9:
            preSumOfDigits = sumOfDigits
            sumOfDigits, sumOfDigits_str = self.sum_digits(sumOfDigits)
            soln_stmt = f"""
            The sum of digits of {preSumOfDigits} = {sumOfDigits}
            """
            soln_stmts.append(soln_stmt.strip())
            pass

        if isDivisible != isDivisible_sumOfDigits:
            soln_stmt = f"""
            <h1>ERROR:</h1>
            """
            soln_stmts.append(soln_stmt.strip())
    
        
        if isDivisible_sumOfDigits:
            soln_stmt = f"""
            {sumOfDigits} is divisible by divisor {divisor}. 
            Hence, {dividend} is also divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass
        else:
            soln_stmt = f"""
            {sumOfDigits} is not divisible by divisor {divisor}. 
            Hence, {dividend} is also not divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass
        

        answer_s = f"""
        {isDivisible_sumOfDigits}
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            'isDivisible': isDivisible,
            }
        
        return result
        pass

    def get_problem_divisible_by_11(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
 
        divisor = kwargs.get('divisor', None)
        dividend = kwargs.get('dividend', None)
        
        if divisor is None:
            divisor = 11
            
        if dividend is None:
            dividend = random.choice([random.randint(0, 1000000),
                                      divisor * random.randint(0, 100000)])

        
        isDivisible = round(dividend / divisor, self._precision) == dividend // divisor
        
        sumOfDigits_odd, sumOfDigits_odd_str = self.sum_digits(dividend, sum_type = 'odd')
        sumOfDigits_even, sumOfDigits_even_str = self.sum_digits(dividend, sum_type = 'even')
        
        diffOfSums = abs(sumOfDigits_odd - sumOfDigits_even)
        isDivisible_diffOfSums = round(diffOfSums / divisor, self._precision) == diffOfSums // divisor
        
        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        Take the sum of alternate digits of dividend {dividend} 
        and find their difference.\nIf the difference is divisible by {divisor}, 
        the number is also divisible by {divisor}

        
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        dividend_list = list(str(dividend))
        
        even_color_list = []
        odd_color_list = []
        for idx, item in enumerate(dividend_list):
            item_color_str = f"""<span style="color:red;">{item}</span>"""
            if (idx + 1) % 2 == 0:
                even_color_list.append(item_color_str)
                odd_color_list.append(item)
            else:
                even_color_list.append(item)
                odd_color_list.append(item_color_str)
            pass
        
        even_color_str = "".join(even_color_list)
        odd_color_str = "".join(odd_color_list)
        
        
        soln_stmt = f"""
        The sum of digits of {odd_color_str} in odd positions 
        = {sumOfDigits_odd_str} = {sumOfDigits_odd}.
        
        The sum of digits of {even_color_str} in even positions 
        = {sumOfDigits_even_str} = {sumOfDigits_even}.
        
        The difference of the above sums 
        =  {sumOfDigits_odd} -  {sumOfDigits_even}
        =  {diffOfSums}
        
        """
        soln_stmts.append(soln_stmt.strip())


        if isDivisible != isDivisible_diffOfSums:
            soln_stmt = f"""
            <h1>ERROR:</h1>
            """
            soln_stmts.append(soln_stmt.strip())
    
        
        if isDivisible_diffOfSums:
            soln_stmt = f"""
            {diffOfSums} is divisible by divisor {divisor}. 
            Hence, {dividend} is also divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass
        else:
            soln_stmt = f"""
            {diffOfSums} is not divisible by divisor {divisor}. 
            Hence, {dividend} is also not divisible by {divisor}.
            """
            soln_stmts.append(soln_stmt.strip())
            pass

        answer_s = f"""
        {isDivisible}
        """
        
        soln_s = "\n\n".join(soln_stmts)
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            'isDivisible': isDivisible,
            }
        
        return result
        pass

    def get_problem_divisible_by_powers_of_2_5(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
 
        divisor_base = random.choice([2, 5])
        divisor_exp = random.choice([2, 4, 3, 5])
        
        divisor = divisor_base ** divisor_exp
        dividend = random.choice([random.randint(0, 10 ** (divisor_exp + 3)),
                                  divisor * random.randint(0, 100000)])
        
        if random.randint(1, 5) == 1:
            dividend_str = str(dividend)
            divisor_base_str = str(divisor_base * random.randint(1, divisor_exp))
            zero_str = "0".zfill(random.randint(1, divisor_exp))
            dividend_str = f"{dividend_str}{zero_str}{divisor_base_str}"
            dividend = int(dividend_str)
            pass
        
        isDivisible = dividend % divisor == 0

        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        divisor_ltx = list(f"{divisor_base}" * divisor_exp)
        divisor_ltx = f"\\; \\times \\;".join(divisor_ltx)
        
        soln_stmts = []
        
        soln_stmt = f"""
        $\\displaystyle 
        {latex(divisor)} = {divisor_ltx}
        $
        <br/>
        <br/>
        As {divisor_base} is repeated {divisor_exp} times,
        we will check last {divisor_exp} digits of {dividend} 
        to find it is divisible by {divisor} or not.
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        
        
        res_digits = divisor_exp
        mod_dividend_str = str(dividend)[-res_digits:]
        mod_dividend = int(mod_dividend_str)
        mod_dividend_str = mod_dividend_str.zfill(res_digits)
        
        while len(mod_dividend_str) > 0:
            
            if mod_dividend == divisor_base:
                soln_stmt = f"""
                <h3>Is {mod_dividend_str} divisible by {divisor_base}?</h3>
                {mod_dividend_str} is divisible by {divisor_base}.
                
                Hence, {dividend} is also divisible by {divisor}. 
                """
                soln_stmts.append(soln_stmt.strip())
                break

            
            step_result = self.get_problem_divisible_by_2_5(dividend = mod_dividend, 
                                                            divisor = divisor_base)
            step_soln_s = step_result.get('soln_s', None)
            step_isDivisible = step_result.get('isDivisible', False)


            if not step_isDivisible:
                soln_stmt = f"""
                <h3>Is {mod_dividend_str} divisible by {divisor_base}?</h3>
                {step_soln_s.strip()}
                
                Hence, {dividend} is also not divisible by {divisor}. 
                """
                soln_stmts.append(soln_stmt.strip())
                break
            
            res_digits = res_digits - 1
            
            temp_dividend = mod_dividend // divisor_base
            
            soln_stmt = f"""
            <h3>Is {mod_dividend_str} divisible by {divisor_base}?</h3>
            {step_soln_s.strip()}
            """
            soln_stmts.append(soln_stmt.strip())

            if res_digits > 0:
                soln_stmt = f"""
                $\\displaystyle 
                \\frac{{{mod_dividend}}} {{{divisor_base}}} = {temp_dividend}
                $.
                
                So, let us check last {res_digits} digit of {temp_dividend}.
                """
                soln_stmts.append(soln_stmt.strip())

            mod_dividend_str = str(temp_dividend)[-res_digits:]
            mod_dividend = int(mod_dividend_str)
            mod_dividend_str = mod_dividend_str.zfill(res_digits)
            pass
        
        soln_stmt = f"""
        """
        soln_stmts.append(soln_stmt.strip())



        answer_s = f"""
        {isDivisible}
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        
        return result
        pass

    def get_problem_divisible_by_6(self, **kwargs):
        sInfo = f"""Info {self.__class__.__name__}.{inspect.stack()[0][3]}: 
        kwargs = {kwargs}
        """
        self._log(sInfo.strip())
        
        
        divisor = 6
        dividend = divisor * random.randint(0, 100000)
        
        if random.randint(1, 2) == 1:
            dividend = dividend + random.randint(1, divisor)
            pass
        
        isDivisible = dividend % divisor == 0

        prob_s = f"""
        Is {dividend} divisible by {divisor}?
        """
        
        
        soln_stmts = []
        
        divisor_factors = [2, 3]
        
        divisor_ltx = f"{divisor_factors[0]} \\times {divisor_factors[1]}"
        
        soln_stmt = f"""
        As $\\displaystyle 
        {latex(divisor)} = {divisor_ltx}
        $, 
        we will check divisibility of {dividend} with {divisor_factors[0]} 
        and {divisor_factors[1]}.
        """
        soln_stmts.append(soln_stmt.replace("\n", " ").strip())
        
        
        for divisor_factor in divisor_factors:
            
            if divisor_factor == 2:
                step_result = self.get_problem_divisible_by_2_5(dividend = dividend, 
                                                                divisor = divisor_factor)
            else:
                step_result = self.get_problem_divisible_by_3_9(dividend = dividend, 
                                                                divisor = divisor_factor)
                
            step_soln_s = step_result.get('soln_s', None)
            step_isDivisible = step_result.get('isDivisible', False)
            
            soln_stmt = f"""
            <h3>Is {dividend} divisible by {divisor_factor}?</h3>
            {step_soln_s.strip()}
            """
            soln_stmts.append(soln_stmt.strip())

            if not step_isDivisible:
                break
            pass

        if isDivisible:
            soln_stmt = f"""
            Hence, {dividend} is also divisible by {divisor}. 
            """
            soln_stmts.append(soln_stmt.strip())
        else:
            soln_stmt = f"""
            Hence, {dividend} is also not divisible by {divisor}. 
            """
            soln_stmts.append(soln_stmt.strip())

        answer_s = f"""
        {isDivisible}
        """
        
        soln_s = "\n\n".join(soln_stmts)
                
        result = {
            'prob_s': prob_s.strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        
        return result
        pass

    def _SAMPLE(self, **kwargs):
        
        prob_s = f"""
        """
        
        soln_stmts = []
        
        soln_stmt = f"""
        """
        soln_stmts.append(soln_stmt.strip())
        
        soln_stmt = f"""
         """
        soln_stmts.append(soln_stmt.strip())

        answer_s = f"""
        """
        
        soln_s = "\n\n".join(soln_stmts)
        
                
        result = {
            'prob_s': prob_s.replace("\n", " ").strip(),
            'soln_s': soln_s.strip(),
            'answer_s': answer_s.strip(),
            }
        
        return result
        pass


    def sum_digits(self, n, sum_type = 'all'):
        if sum_type == 'even':
            n = [x[1] for x in enumerate(list(str(n)))
                 if (x[0] + 1) % 2 == 0]
            n = int("".join(n))

        if sum_type == 'odd':
            n = [x[1] for x in enumerate(list(str(n)))
                 if (x[0] + 1) % 2 != 0]
            n = int("".join(n))

        r_str = " + ".join([x for x in list(str(n))] )  
        
        r = 0
        while n:
            r, n = r + n % 10, n // 10
            
        return r, r_str

    pass
#class DivisibilityHelper:
