提示你
先找出運算子 (+、-、*、/)
再來
算數學
String.includes
是用來找出字串有沒有存在你要找的目標
e.g.
'8*2'.includes('*'); // true
'8*2'.includes('/'); // false
String.split
是用來切字串
e.g.
'8*2'.split('*') //["8", "2"]
看起來沒有括號的四則運算
題目也都只有一個運算子
應該很簡單的
ps. 哪間學校教 Typescript 這麼潮XD
標準寫法
let calc = function (calcString: string) {
if (如果運算式有 "*") {
const data = 處理過只有數字的陣列
console.log(第一個數字 * 第二個數字)
}
}
叛逆寫法
let calc = function (calcString: string) {
console.log(eval(calcString))
}
藉機練習了一下中序式轉後序式並計算後序式...以前都沒好好寫過XD
先準備環境:
makedir mathrun; cd mathrun
npm init
touch index.js
npm i --save minimist
index.js
const args = require('minimist')(process.argv.slice(2));
if(args._.length === 1) {
main(args._[0]);
} else {
help();
}
function main(str) {
console.log(`input:\t\t${str}`);
let a = tokenize(str);
console.log(`tokenized:\t${JSON.stringify(a)}`);
let b = infix2postfix(a);
console.log(`postfix:\t${JSON.stringify(b)}`);
let c = calculate(b);
console.log(`result:\t\t${c[c.length-1]}`);
}
function help() {
console.log('[Usage] node mathrun {string of math expression to run}')
}
function tokenize(str) {
str = str.replace(/[ ]+/g, '');//去掉空格
let ret = [];
let tmp = '';
for(let i=0; i<str.length; i++) {
if(isNaN(parseInt(str[i]))) {
//非數字,可能是運算子或括號
if(tmp.length > 0) {
ret.push(tmp);
tmp = '';
}
switch(str[i]) {
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
ret.push(str[i]);
break;
default:
throw new Error(`Illegal Operator: ${str[i]}.`);
}
} else {
//數字
tmp += str[i];
}
}
if(tmp.length > 0) {
ret.push(tmp);
}
return ret;
}
function infix2postfix(arr) {
let ret = [];
let stk = [];
arr.forEach(s => {
if(isNaN(parseInt(s))) {
switch(s) {
case '(':
stk.push(s);
break;
case ')':
while(stk.length > 0 && stk[stk.length-1] !== '(') {
ret.push(stk.pop());
}
if(stk[stk.length-1] === '(') stk.pop();
break;
case '*':
case '/':
case '+':
case '-':
if(preced(s) > preced(stk[stk.length-1])) {
stk.push(s);
} else {
while(stk.length > 0 && preced(s) <= preced(stk[stk.length-1])) {
ret.push(stk.pop())
}
stk.push(s);
}
break;
default:
throw new Error(`Illegal Operator: ${s}`);
break;
}
} else {
ret.push(s);
}
});
while(stk.length > 0) {
ret.push(stk.pop());
}
return ret;
}
function preced(s) {
let ret = 0;
switch(s) {
case '*':
case '/':
ret = 2;
break;
case '+':
case '-':
ret = 1;
break;
default:
ret = 0;
}
return ret;
}
function calculate(arr) {
let stk = [];
let op = {
'+': (arg0, arg1) => arg0 + arg1,
'-': (arg0, arg1) => arg1 - arg0,
'*': (arg0, arg1) => arg0 * arg1,
'/': (arg0, arg1) => arg1 / arg0
}
arr.forEach(s => {
if(isNaN(parseInt(s))) {
stk.push(op[s](stk.pop(), stk.pop()));
} else {
stk.push(parseInt(s));
}
});
return stk;
}
執行起來:
$ node mathrun 1*4+2*3-4/2+3-5+36/6
input: 1*4+2*3-4/2+3-5+36/6
tokenized: ["1","*","4","+","2","*","3","-","4","/","2","+","3","-","5","+","36","/","6"]
postfix: ["1","4","*","2","3","*","+","4","2","/","-","3","+","5","-","36","6","/","+"]
result: 12
有括號的話:
$ node mathrun "(1+2)*(3+4)"
input: (1+2)*(3+4)
tokenized: ["(","1","+","2",")","*","(","3","+","4",")"]
postfix: ["1","2","+","3","4","+","*"]
result: 21