/**
- 根据表达式计算字母数
- 说明:
- 给定一个描述字母数量的表达式,计算表达式里的每个字母实际数量
- 表达式格式:
- 字母紧跟表示次数的数字,如 A2B3
- 括号可将表达式局部分组后跟上数字,(A2)2B
- 数字为1时可缺省,如 AB3。
- 示例:
- countOfLetters('A2B3'); // { A: 2, B: 3 }
- countOfLetters('A(A3B)2'); // { A: 7, B: 2 }
- countOfLetters('C4(A(A3B)2)2'); // { A: 14, B: 4, C: 4 }
*/
function multipleToken(tokenStr, multiple) {
return `${tokenStr.substr(0,1)}${tokenStr.substr(1)*multiple}`
}
// tokens array
function flatToken(tokens) {
const flatToken = []
function isOverFlag(str) {
return /\)/.test(str)
}
for (let i = 0; i < tokens.length; i++) {
if (isOverFlag(tokens[i])) {
let newToken = []
let popToken = flatToken.pop()
while (popToken != '(') {
newToken.push(multipleToken(popToken, tokens[i].substr(1)))
popToken = flatToken.pop()
}
flatToken.push(...newToken)
} else {
flatToken.push(tokens[i])
}
}
return flatToken
}
function getValueFromFlatToken(flatToken) {
const obj = {}
flatToken.forEach((item) => {
if (!obj[item.substr(0, 1)]) obj[item.substr(0, 1)] = 0
obj[item.substr(0, 1)] += (+item.substr(1) || 1)
})
return obj
}
function prase(str) {
const tokens = []
let tokenStr = ''
function emitToken() {
if (tokenStr) {
if (tokenStr.length == 1) tokenStr += '1'
tokens.push(tokenStr)
tokenStr = ''
}
}
for (let i = 0; i < str.length; i++) {
const letter = str.substr(i, 1)
if (letter == '(') {
emitToken()
tokens.push('(')
continue
}
if (letter == ')') {
emitToken()
tokenStr += letter
continue
}
const isLetter = (s) => !/[^A-Za-z]/.test(s)
if (isLetter(letter)) {
emitToken()
tokenStr += letter
continue
}
tokenStr += letter
}
emitToken()
return tokens
}
function countOfLetters(letters) {
// prase
// flatToken
// getValueFromFlatToken
return getValueFromFlatToken(flatToken(prase(letters)))
}