<p>Given a string <code>s</code>, return whether <code>s</code> is a <strong>valid number</strong>.<br />
<br />
For example, all the following are valid numbers: <code>&quot;2&quot;, &quot;0089&quot;, &quot;-0.1&quot;, &quot;+3.14&quot;, &quot;4.&quot;, &quot;-.9&quot;, &quot;2e10&quot;, &quot;-90E3&quot;, &quot;3e+7&quot;, &quot;+6e-1&quot;, &quot;53.5e93&quot;, &quot;-123.456e789&quot;</code>, while the following are not valid numbers: <code>&quot;abc&quot;, &quot;1a&quot;, &quot;1e&quot;, &quot;e3&quot;, &quot;99e2.5&quot;, &quot;--6&quot;, &quot;-+3&quot;, &quot;95a54e53&quot;</code>.</p>

<p>Formally, a&nbsp;<strong>valid number</strong> is defined using one of the following definitions:</p>

<ol>
	<li>An <strong>integer number</strong> followed by an <strong>optional exponent</strong>.</li>
	<li>A <strong>decimal number</strong> followed by an <strong>optional exponent</strong>.</li>
</ol>

<p>An <strong>integer number</strong> is defined with an <strong>optional sign</strong> <code>&#39;-&#39;</code> or <code>&#39;+&#39;</code> followed by <strong>digits</strong>.</p>

<p>A <strong>decimal number</strong> is defined with an <strong>optional sign</strong> <code>&#39;-&#39;</code> or <code>&#39;+&#39;</code> followed by one of the following definitions:</p>

<ol>
	<li><strong>Digits</strong> followed by a <strong>dot</strong> <code>&#39;.&#39;</code>.</li>
	<li><strong>Digits</strong> followed by a <strong>dot</strong> <code>&#39;.&#39;</code> followed by <strong>digits</strong>.</li>
	<li>A <strong>dot</strong> <code>&#39;.&#39;</code> followed by <strong>digits</strong>.</li>
</ol>

<p>An <strong>exponent</strong> is defined with an <strong>exponent notation</strong> <code>&#39;e&#39;</code> or <code>&#39;E&#39;</code> followed by an <strong>integer number</strong>.</p>

<p>The <strong>digits</strong> are defined as one or more digits.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">s = &quot;0&quot;</span></p>

<p><strong>Output:</strong> <span class="example-io">true</span></p>
</div>

<p><strong class="example">Example 2:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">s = &quot;e&quot;</span></p>

<p><strong>Output:</strong> <span class="example-io">false</span></p>
</div>

<p><strong class="example">Example 3:</strong></p>

<div class="example-block">
<p><strong>Input:</strong> <span class="example-io">s = &quot;.&quot;</span></p>

<p><strong>Output:</strong> <span class="example-io">false</span></p>
</div>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>1 &lt;= s.length &lt;= 20</code></li>
	<li><code>s</code> consists of only English letters (both uppercase and lowercase), digits (<code>0-9</code>), plus <code>&#39;+&#39;</code>, minus <code>&#39;-&#39;</code>, or dot <code>&#39;.&#39;</code>.</li>
</ul>

class Solution:
    def isNumber(self, s: str) -> bool:
        """
        2
        0089
        -0.1
        +3.14
        4.
        -.9
        2e10
        -90E3

        Integer followed by optional exponent
        decimal with optional exponent
        integer is defined wtih - or +
        followed by digits
        
        This is Integer to English words vibe question.
        all possible characters we have
        [0-9]
        .
        e,E
        -, +

        [0,9] can occur anywhere.
        . cannot occur while defining an exponent like 99e2.5

        e/E cannot occur 
            - if there is no num before it 
            - after it there is no {-,+}[0-9]
        
        - and + cannot occur if there is a - or + before it or after.
        anything else is invalid 

        but how many cases can we have

        what about 2e2e2? CONFIRMED INVALID
        - given 2e2.5 is invalid this may also be invalid
        - it's possible its not tho

        1. splitting at E should give 2 non-empty elements.
            - it may not matter if its 3 elements
            - but if its less than 2 its invalid
            because it's either e3 or 3e. both invalid
            for each string:
                check the - and + 
                check the . 
                    this can only happen in the first element.
                    remember 2.5e is invalid. but 2.5e3 is not
        
        and assumption is are we allowed to modify the input?
        because if we can I can convert it to all lowercase then split at "e"
        otherwise we have to split at either (might be possible)

        """
        s = s.replace("E","e")
        elems = s.split("e")
        # FOR THIS CASE "92e1740e91"
        if len(elems) > 2:
            return False 
    
        for i in range(len(elems)):
            cur_num = elems[i]
            # eitehr e3 or 3e case
            if cur_num == "":
                return False
            # check this number
            print(cur_num)
            found_dot = False

            for j in range(len(cur_num)):
                # -12-1 also invalid
                # + by itself is invalid
                # need to have num after it
                if cur_num[j] in {"+","-"}:
                    # if its not at the start has to be invalid
                    if j != 0 or len(cur_num) == 1: 
                        return False
                # 2.2.2 also invalid tho
                # . by itself is invalid
                # .+ is invalid handled above
                # +. is invalid
                #+.8 is valid
                # if prev is a + or -, next is not a number then invalid
                elif cur_num[j] == ".":
                    if (found_dot or len(cur_num) == 1 or i != 0):
                        return False
                    if j > 0:
                        prev = cur_num[j-1]
                        if (prev in {"+","-"}):
                            if j == len(cur_num)-1:
                                return False
                            elif not cur_num[j+1].isnumeric():
                                return False
                    found_dot = True


                elif not cur_num[j].isnumeric():
                    return False
            
        return True
                
                    
                

            

16600