-
Notifications
You must be signed in to change notification settings - Fork 0
Refact code test #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| language: "pt-BR" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,4 @@ | ||
| fegwegwefgweq | ||
|
|
||
|
|
||
| TESTANDO O CODE RABBIT |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,132 +1,193 @@ | ||
| function solve(firstNumber: number, secondNumber: number, operator: string): number { | ||
| const operations: { [index: string]: Function } = { | ||
| "+": () => firstNumber + secondNumber, | ||
| "-": () => firstNumber - secondNumber, | ||
| "*": () => firstNumber * secondNumber, | ||
| "/": () => firstNumber / secondNumber | ||
| }; | ||
| type Operation = { | ||
| priority: number, | ||
| solve: (first: number, second: number) => number | ||
| }; | ||
|
|
||
| return operations[operator](); | ||
| interface ExpressionParserInterface { | ||
| parse(expression: string): Array<string> | ||
| } | ||
|
|
||
| class ExpressionParser implements ExpressionParserInterface { | ||
| #operators: Set<string> = new Set(["+", "-", "*", "/"]); | ||
|
|
||
| function solveSimplifiedExpr(output: Array<string>, operators: Array<string>): void { | ||
| const secondNumber = Number(output.pop()); | ||
| const firstNumber = Number(output.pop()); | ||
| #parenthesesStack: Array<string>; | ||
| #expression: Array<string>; | ||
|
|
||
| const operator = operators.pop(); | ||
| #lastToken: string | null; | ||
| #hasDecimal: boolean; | ||
| #number: string; | ||
|
|
||
| if (operator == null) | ||
| throw "Operation Not Supported."; | ||
| #isDigit(token: string) { | ||
| return token.charCodeAt(0) >= "0".charCodeAt(0) | ||
| && token.charCodeAt(0) <= "9".charCodeAt(0); | ||
| } | ||
|
|
||
| #isNegativeSignal(token: string) { | ||
| return !this.#isValidNumber() | ||
| && token === "-" | ||
| && (this.#lastToken == null | ||
| || this.#lastToken == "(" | ||
| || this.#isOperator(this.#lastToken)); | ||
| } | ||
|
|
||
| output.push(solve(firstNumber, secondNumber, operator).toString()); | ||
| } | ||
| #isOperator(token: string) { | ||
| return this.#operators.has(token); | ||
| } | ||
|
|
||
| function isDigit(character: string) { | ||
| return character.charCodeAt(0) >= "0".charCodeAt(0) | ||
| && character.charCodeAt(0) <= "9".charCodeAt(0); | ||
| } | ||
| #isValidNumber() { | ||
| return this.#number.length > 0; | ||
| } | ||
|
|
||
| #addNumberToExpression() { | ||
| this.#expression.push(this.#number); | ||
| this.#hasDecimal = false; | ||
| this.#number = ""; | ||
| } | ||
|
|
||
| function parseExpression(expression: string) { | ||
| const operators: Array<string> = ["+", "-", "*", "/"]; | ||
| const expr: Array<string> = []; | ||
| const parenthesesStack: Array<string> = []; | ||
|
|
||
| let lastToken: string | null = null; | ||
| let number = ""; | ||
| let hasDecimal = false; | ||
|
|
||
| for (const token of expression.replaceAll(" ", "")) { | ||
| if (isDigit(token)) { | ||
| number += token; | ||
| } else if (token === ".") { | ||
| if (hasDecimal || !number.length) | ||
| throw "Número decimal mal formado."; | ||
| number += token; | ||
| hasDecimal = true; | ||
| } else if (token === "(") { | ||
| parenthesesStack.push(token); | ||
| expr.push(token); | ||
| hasDecimal = false; | ||
| } else if (token === ")") { | ||
| if (!parenthesesStack.length) | ||
| throw "Parêntese fechado sem abertura correspondente."; | ||
| parenthesesStack.pop(); | ||
|
|
||
| if (number.length) { | ||
| expr.push(number); | ||
| number = ""; | ||
| hasDecimal = false; | ||
| } | ||
| #addDecimalPoint() { | ||
| if (this.#hasDecimal || !this.#isValidNumber()) | ||
| throw "Número decimal mal formado."; | ||
|
|
||
| expr.push(token); | ||
| } else if (operators.indexOf(token) >= 0) { | ||
| if (!number.length | ||
| && token === "-" | ||
| && (lastToken == null | ||
| || operators.indexOf(lastToken) >= 0 | ||
| || lastToken == "(")) { | ||
| number += token; | ||
| } else { | ||
| if (!number.length) | ||
| throw `Operador '${token}' mal posicionado na expressão.`; | ||
| expr.push(number); | ||
| number = ""; | ||
| hasDecimal = false; | ||
| expr.push(token); | ||
| } | ||
| } else throw `Caractere inválido na expressão: '${token}'`; | ||
| this.#hasDecimal = true; | ||
| this.#number += "."; | ||
| } | ||
|
|
||
| #openParentheses() { | ||
| this.#parenthesesStack.push("("); | ||
| this.#expression.push("("); | ||
| this.#hasDecimal = false; | ||
| } | ||
|
|
||
| lastToken = token; | ||
| #closeParentheses() { | ||
| if (!this.#parenthesesStack.length) | ||
| throw "Parêntese fechado sem abertura correspondente."; | ||
| this.#parenthesesStack.pop(); | ||
|
|
||
| if (this.#isValidNumber()) | ||
| this.#addNumberToExpression(); | ||
|
|
||
| this.#expression.push(")"); | ||
| } | ||
|
|
||
| if (!number.length && ( | ||
| lastToken == null | ||
| || operators.indexOf(lastToken) >= 0)) | ||
| throw `Operador '${lastToken}' mal posicionado na expressão.`; | ||
| #handleOperator(operator: string) { | ||
| if (this.#isNegativeSignal(operator)) { | ||
| this.#number += operator; | ||
| } else { | ||
| if (!this.#isValidNumber()) | ||
| throw `Operador '${operator}' mal posicionado na expressão.`; | ||
| this.#addNumberToExpression(); | ||
| this.#expression.push(operator); | ||
| } | ||
| } | ||
|
|
||
| parse(expression: string): Array<string> { | ||
| this.#parenthesesStack = []; | ||
| this.#expression = []; | ||
|
|
||
| this.#hasDecimal = false; | ||
| this.#lastToken = null; | ||
| this.#number = ""; | ||
|
|
||
| for (const token of expression.replaceAll(" ", "")) { | ||
| if (this.#isDigit(token)) { | ||
| this.#number += token; | ||
| } else if (token === ".") { | ||
| this.#addDecimalPoint(); | ||
| } else if (token === "(") { | ||
| this.#openParentheses(); | ||
| } else if (token === ")") { | ||
| this.#closeParentheses(); | ||
| } else if (this.#isOperator(token)) { | ||
| this.#handleOperator(token); | ||
| } else throw `Caractere inválido na expressão: '${token}'`; | ||
|
|
||
| this.#lastToken = token; | ||
| } | ||
|
|
||
| if (!this.#isValidNumber() && ( | ||
| this.#lastToken == null | ||
| || this.#isOperator(this.#lastToken))) | ||
| throw `Operador '${this.#lastToken}' mal posicionado na expressão.`; | ||
|
|
||
| if (parenthesesStack.length) | ||
| throw "Parêntese aberto sem fechamento correspondente."; | ||
| if (this.#isValidNumber()) | ||
| this.#addNumberToExpression(); | ||
|
|
||
| if (number.length) | ||
| expr.push(number); | ||
| if (this.#parenthesesStack.length) | ||
| throw "Parêntese aberto sem fechamento correspondente."; | ||
|
|
||
| return expr; | ||
|
|
||
| return this.#expression; | ||
| } | ||
| } | ||
|
|
||
| function solveExpression(expression: string) { | ||
| const priorities: { [index: string]: number } = { | ||
| "+": 1, | ||
| "-": 1, | ||
| "*": 2, | ||
| "/": 2 | ||
| class ExpressionSolver { | ||
| #operations: { [index: string]: Operation } = { | ||
| "+": { priority: 1, solve: (first: number, second: number) => first + second }, | ||
| "-": { priority: 1, solve: (first: number, second: number) => first - second }, | ||
| "*": { priority: 2, solve: (first: number, second: number) => first * second }, | ||
| "/": { priority: 2, solve: (first: number, second: number) => first / second } | ||
| }; | ||
| #parser: ExpressionParserInterface; | ||
| #operators: Array<string>; | ||
| #output: Array<string>; | ||
|
|
||
| const operators: Array<string> = []; | ||
| const output: Array<string> = []; | ||
|
|
||
| for (const token of parseExpression(expression)) { | ||
| if (token === "(") { | ||
| operators.push(token); | ||
| } else if (token === ")") { | ||
| while (operators[operators.length - 1] !== "(") | ||
| solveSimplifiedExpr(output, operators); | ||
| operators.pop(); | ||
| } else if (priorities.hasOwnProperty(token)) { | ||
| while (operators.length | ||
| && operators[operators.length - 1] != "(" | ||
| && priorities[operators[operators.length - 1]] >= priorities[token]) | ||
| solveSimplifiedExpr(output, operators); | ||
| operators.push(token); | ||
| } else { | ||
| output.push(token); | ||
| } | ||
| constructor(expressionParse: ExpressionParserInterface) { | ||
| this.#parser = expressionParse; | ||
| } | ||
|
|
||
| while (operators.length) | ||
| solveSimplifiedExpr(output, operators); | ||
| #solve() { | ||
| const secondNumber = Number(this.#output.pop()); | ||
| const firstNumber = Number(this.#output.pop()); | ||
| const operator = this.#operators.pop(); | ||
|
|
||
| if (operator == null || !this.#operations.hasOwnProperty(operator)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Switch from using Avoid calling -if (operator == null || !this.#operations.hasOwnProperty(operator))
- throw "Operation Not Supported.";
+if (operator == null || !Object.hasOwn(this.#operations, operator))
+ throw new Error("Operation Not Supported.");
...
-return this.#operations.hasOwnProperty(token);
+return Object.hasOwn(this.#operations, token);Also applies to: 155-155 🧰 Tools🪛 Biome (1.9.4)[error] 143-143: Do not access Object.prototype method 'hasOwnProperty' from target object. It's recommended using Object.hasOwn() instead of using Object.hasOwnProperty(). (lint/suspicious/noPrototypeBuiltins) |
||
| throw "Operation Not Supported."; | ||
|
|
||
| const result = this.#operations[operator].solve(firstNumber, secondNumber); | ||
| this.#output.push(result.toString()); | ||
| } | ||
|
|
||
| #lastOperator() { | ||
| return this.#operators[this.#operators.length - 1]; | ||
| } | ||
|
|
||
| #isOperator(token: string) { | ||
| return this.#operations.hasOwnProperty(token); | ||
| } | ||
|
|
||
| return Number(output.pop()); | ||
|
|
||
| solve(expression: string): number { | ||
| this.#operators = []; | ||
| this.#output = []; | ||
|
|
||
| for (const token of this.#parser.parse(expression)) { | ||
| if (token === "(") { | ||
| this.#operators.push(token); | ||
| } else if (token === ")") { | ||
| while (this.#lastOperator() !== "(") | ||
| this.#solve(); | ||
| this.#operators.pop(); | ||
| } else if (this.#isOperator(token)) { | ||
| while (this.#operators.length | ||
| && this.#lastOperator() != "(" | ||
| && this.#operations[this.#lastOperator()].priority >= this.#operations[token].priority) | ||
| this.#solve(); | ||
| this.#operators.push(token); | ||
| } else { | ||
| this.#output.push(token); | ||
| } | ||
| } | ||
|
|
||
| while (this.#operators.length) | ||
| this.#solve(); | ||
|
|
||
| return Number(this.#output.pop()); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| const handler = new ExpressionParser(); | ||
| const solver = new ExpressionSolver(handler); | ||
|
|
||
| // console.log(solver.solve("1 + 2 * 3")) | ||
| console.log(solver.solve("1 + 2 * 3")) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Prefer throwing Error objects instead of strings.
Using
throw new Error(...)ensures stack traces are correctly captured and aligns with standard JavaScript/TypeScript practices.Also applies to: 63-63, 77-77, 102-102, 110-110, 116-116