""" Solution By: Reniz Shah Topic: Deterministic Finite Automaton (DFA) Given a string s, return whether s is a valid number or not Input: s = -90E3 Output: True Leetcode link: https://leetcode.com/problems/valid-number/description/ """ from enum import Enum from typing import Dict class CharType(Enum): NUMERIC = 'NUMERIC' SIGN = 'SIGN' EXPONENT = 'EXPONENT' DECIMAL = 'DECIMAL' class State(Enum): INITIAL = 'INITIAL' SIGNED = 'SIGNED' WHOLE = 'WHOLE' FRACTIONAL = 'FRACTIONAL' FRACTION = 'FRACTION' EXPONENTIAL = 'EXPONENTIAL' EXP_SIGN = 'EXP_SIGN' EXP_NUMBER = 'EXP_NUMBER' state_machine : Dict[State, Dict[CharType, State]] = { State.INITIAL: {CharType.NUMERIC: State.WHOLE, CharType.SIGN: State.SIGNED, CharType.DECIMAL: State.FRACTIONAL}, State.SIGNED: {CharType.NUMERIC: State.WHOLE, CharType.DECIMAL: State.FRACTIONAL}, State.WHOLE: {CharType.NUMERIC: State.WHOLE, CharType.DECIMAL: State.FRACTION, CharType.EXPONENT: State.EXPONENTIAL}, State.FRACTIONAL: {CharType.NUMERIC: State.FRACTION}, State.FRACTION: {CharType.NUMERIC: State.FRACTION, CharType.EXPONENT: State.EXPONENTIAL}, State.EXPONENTIAL: {CharType.NUMERIC: State.EXP_NUMBER, CharType.SIGN: State.EXP_SIGN}, State.EXP_SIGN: {CharType.NUMERIC: State.EXP_NUMBER}, State.EXP_NUMBER: {CharType.NUMERIC: State.EXP_NUMBER}, } def classify_char(char: str) -> CharType | None: """ Classifies a character into one of the following categories: - 'CharType.NUMERIC': if the character is a digit (0-9) - 'CharType.SIGN': if the character is a plus sign (+) or a minus sign (-) - 'CharType.EXPONENT': if the character is an 'e' or 'E' (used in exponential notation) - 'CharType.DECIMAL': if the character is a decimal point (.) - None: if the character does not fit into any of the above categories or size of char is not 1 Parameters: char (str): The character to be classified Returns: CharType: The classification of the character >>> classify_char('2') >>> classify_char('-') >>> classify_char('e') >>> classify_char('.') >>> classify_char('') >>> classify_char('0') >>> classify_char('01') """ if len(char) != 1: return None if char.isdigit(): return CharType.NUMERIC if char in "+-": return CharType.SIGN if char in "eE": return CharType.EXPONENT if char == ".": return CharType.DECIMAL return None def is_valid_number(s: str) -> bool: """ This function checks if the input string represents a valid number. It uses a finite state machine to parse the input string, transitioning between states based on the character type. The function returns True if the input string represents a valid number, and False otherwise. A valid number is defined as a string that can be parsed into an integer, decimal, or exponent. >>> is_valid_number("2") True >>> is_valid_number("0089") True >>> is_valid_number("-0.1") True >>> is_valid_number("+3.14") True >>> is_valid_number("4.") True >>> is_valid_number("-.9") True >>> is_valid_number("2e10") True >>> is_valid_number("-90E3") True >>> is_valid_number("3e+7") True >>> is_valid_number("+6e-1") True >>> is_valid_number("53.5e93") True >>> is_valid_number("-123.456e789") True >>> is_valid_number("abc") False >>> is_valid_number("1a") False >>> is_valid_number("1e") False >>> is_valid_number("e3") False >>> is_valid_number("99e2.5") False >>> is_valid_number("--6") False >>> is_valid_number("-+3") False >>> is_valid_number("95a54e53") False >>> is_valid_number(".") False """ valid_final_states = {State.WHOLE, State.FRACTION, State.EXP_NUMBER} current_state = State.INITIAL for char in s: char_type = classify_char(char) if char_type is None or char_type not in state_machine[current_state]: return False current_state = state_machine[current_state][char_type] return current_state in valid_final_states if __name__ == "__main__": import doctest doctest.testmod()