Very long JavaScript code using FSM :)


  • 0
    C

    JavaScript version using FSM, works like parseInt(). Sure, I had to modify this code to pass submit test-cases. :)

    /**
     * @param {string} str
     * @return {number}
     */
    "use strict";
    
    var _atoi = function(str) {
        // to simplify
        str = str.toLowerCase()
        
        const NUMBER_RANGE = '0123456789abcdef'
        
        // by default, scale is 10
        var scale,
            minus = false,
            tokenMap = undefined
    
        // result will be stored at here    
        var accumulator = 0
    
        // token
        const   PLUS_SIGN   = 'PLUS_SIGN',
                MINUS_SIGN  = 'MINUS_SIGN',
                EX          = 'EX',
                ZERO        = 'ZERO',
                NUMBER      = 'NUMBER',
                EOF         = 'EOF'
    
        // get number range by scale
        var setScale = function(_scale) {
            if (0 > scale || 16 < scale ) {
                throw new Error('Wrong scale')
            }
            
            const defaultMap = {
                '0': ZERO,
                'x': EX,
                '+': PLUS_SIGN,
                '-': MINUS_SIGN,
            }
    
            // set scale
            scale = _scale
    
            // clone tokenMap from defaultMap
            tokenMap = JSON.parse(JSON.stringify(defaultMap))
            
            // insert valid values into tokenMap, and start from index 1 for skipping zero
            for (var idx = 1 ; idx < scale ; idx ++) {
                var char = NUMBER_RANGE.charAt(idx)
                tokenMap[char] = NUMBER
            }
        }
        
        // To simplify get token, we'll set value in token
        var nextToken = function() {
            if (str.length) {
                var char = str.charAt(0)
                str = str.substr(1, str.length)
        
                // if char doesn't exist in tokenMap        
                if (!tokenMap.hasOwnProperty(char)) {
                    // invalid token
                    throw new Error('Invalid or unexpected token: ' + char)
                }
                
                return {
                    type: tokenMap[char],
                    value: char
                }
            }
    
            return {
                type: 'EOF',
                value: null
            }
        }
    
        // states
        const   S           = 'S',
                PLUS        = 'PLUS',
                MINUS       = 'MINUS',
                SCALE8      = 'SCALE8',
                SCALE16     = 'SCALE16',
                ACCMUL      = 'ACCMUL',
                FINISH      = 'FINISH'
                
        var rules = {
            'S': {
                possible: {
                    'PLUS_SIGN': PLUS,
                    'MINUS_SIGN': MINUS,
                    'ZERO': SCALE8,
                    'NUMBER': ACCMUL
                }
            },
            'MINUS': {
                callback: function() {
                    minus |= true
    
                    return false
                },
                possible: {
                    'PLUS_SIGN': PLUS,
                    'ZERO': SCALE8,
                    'NUMBER': ACCMUL
                }
            },
            'PLUS': {
                callback: function() {
                    minus |= false
    
                    return false
                },
                possible: {
                    'MINUS_SIGN': MINUS,
                    'ZERO': SCALE8,
                    'NUMBER': ACCMUL
                }
            },
            'SCALE8': {
                callback: function() {
                    setScale(8)
    
                    return false
                },
                possible: {
                    'EX': SCALE16,
                    'ZERO': ACCMUL,
                    'NUMBER': ACCMUL,
                    'EOF': FINISH
                }
            },
            'SCALE16': {
                callback: function() {
                    setScale(16)
    
                    return false
                },
                possible: {
                    'ZERO': ACCMUL,
                    'NUMBER': ACCMUL
                }
            },
            'ACCMUL': {
                callback: function(token) {
                    // convert to integer
                    var value = NUMBER_RANGE.indexOf(token.value)
                    
                    // To avoid zero exception
                    if (token.type == 'ZERO') {
                        value = 0
                    }
                    
                    accumulator = accumulator * scale + value
    
                    return false
                },
                possible: {
                    'ZERO': ACCMUL,
                    'NUMBER': ACCMUL,
                    'EOF': FINISH
                }
            },
            'FINISH': {
                callback: function() {
                    if (minus) {
                        accumulator *= -1
                    }
    
                    return true
                }
            }
        }
        
        // initial state is 'S'
        var state = 'S'
        
        // set default scale is 10
        setScale(10)
        
        do {
            var token = nextToken()
            
            // check possibilities
            if (rules[state].possible.hasOwnProperty(token.type) == false) {
                throw new Error('Invalid state. Expect = ' + JSON.stringify(rules[state].possible))
            }
            
            // transite state
            state = rules[state].possible[token.type]
    
            // call callback function
            var isFinished = rules[state].callback.apply(this, [token])
        } while (!isFinished)
        
        return accumulator
    };
    
    var myAtoi = function(str) {
        const   INT_MAX = 2147483647,
                INT_MIN = -2147483648
    
        try {
            var result = _atoi(str)
            // Seriously it was integer...:)
            return Math.max(Math.min(result, INT_MAX), INT_MIN)
        } catch(e) {
            return 0
        }
    };
    

Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.