-
Notifications
You must be signed in to change notification settings - Fork 267
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Conclusão do Desafio 14 - @JamesStewart-314 (#1168)
* feat: Conclusão do Desafio 14 - @JamesStewart-314 * Pylint Error * Ajuste de Espaçamento * Ajuste de strip * Correção de Lógica * Correção de Lógica --------- Co-authored-by: Allber Fellype <[email protected]>
- Loading branch information
1 parent
9e4df72
commit 86fe613
Showing
3 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
19c61202b5c41fa163e195175d0c061a1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Desafio 14 - Expressões Numéricas | ||
![Python](https://img.shields.io/badge/Python-512BD4?style=flat&logo=python&logoColor=yellow) | ||
![VS Code](https://img.shields.io/badge/VScode-007ACC?style=flat&logo=visualstudiocode&logoColor=white) | ||
|
||
## Descrição do Projeto: | ||
Expressões numéricas consistem numa sequências de operações aplicadas a um conjunto de | ||
valores em ordem de precedência com base nas regras aritméticas preestabelecidas. | ||
O objetivo deste projeto consiste em efetuar a leitura de um arquivo textual contendo uma | ||
expresão numérica por linha e exibir seu respectivo resultado final. Se o programa | ||
encontrar um divisão por zero deverá imprimir ERR DIVBYZERO. | ||
Se o programa encontrar um erro de sintaxe na expressão deverá imprimir ERR SYNTAX. | ||
|
||
## Exemplo do Conteúdo Lido do Arquivo: | ||
``` | ||
1 + 3 | ||
2 - 3 * 2 | ||
2 ^ 3 / 4 | ||
0 * 5 * (4 + 1) | ||
5 + 5 / 0 | ||
5 + + 1 | ||
5 + ( 465 + 1 | ||
``` | ||
## Saídas Esperadas: | ||
``` | ||
4 | ||
-4 | ||
2 | ||
0 | ||
ERR DIVBYZERO | ||
ERR SYNTAX | ||
ERR SYNTAX | ||
``` | ||
## Requisitos para Execução | ||
- Possuir um ambiente virtual Python instalado localmente em sua máquina com a | ||
versão `3.10` ou superior. | ||
Para baixar esta e outras versões, visite o site | ||
<a target="_blank" href="https://www.python.org/downloads/" style="color: lightgreen">Python.org</a> | ||
e siga os procedimentos de instalação para o | ||
seu sistema operacional. | ||
Após a instalação, abra o terminal de comando em sua máquina e digite o comando | ||
`python --version`. O comando deverá informar a versão atual do interpretador de | ||
Python caso o download tenha sido feito corretamente. Certifique-se de possuir uma | ||
versão igual ou superior à `3.10`, caso contrário, o código não funcionará. | ||
|
||
## Instruções para Executar o Código | ||
- Certificando-se de ter instalado corretamente o `Python` em sua | ||
máquina, execute os seguintes comandos: | ||
1. Abra o terminal e navegue até a pasta em que deseja copiar este repositório com o | ||
comando `cd <caminho_absoluto_do_diretótio>`; | ||
2. Em seguida, copie e cole o seguinte código: | ||
`git clone https://github.com/OsProgramadores/op-desafios.git`; | ||
3. Navegue até a pasta contendo o arquivo `solution.py` na árvore do repositório - se | ||
necessário, utilize o comando `cd ".\op-desafios\desafio-14\JamesStewart-314"` | ||
4. Execute o script `"solution.py"` com o comando `python solution.py` | ||
e os resultados deverão ser impressos de maneira formatada na CLI. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import os | ||
import re | ||
import string | ||
import collections | ||
from typing import TextIO | ||
|
||
def get_op_index(math_expression: str, operator: str, exp_s: set[str]) -> int: | ||
return math_expression.index(operator) if operator in exp_s\ | ||
else float('inf') | ||
|
||
|
||
def eval_flat_expression(expression: str) -> str: | ||
numb_exp: list[str] = re.split(r'[\+\-\*\/\^]', expression) | ||
exp_oper: list[str] = re.findall(r'[\+\-\*\/\^]', expression) | ||
while exp_oper: | ||
exp_set: set[str] = set(exp_oper) | ||
if "^" in exp_oper: | ||
oper_idx: int = exp_oper.index('^') | ||
op_a, op_b = map(int, (numb_exp[oper_idx], numb_exp[oper_idx + 1])) | ||
|
||
result: str = str(op_a ** op_b) | ||
|
||
for _ in range(2): | ||
numb_exp.pop(oper_idx) | ||
|
||
exp_oper.pop(oper_idx) | ||
numb_exp.insert(oper_idx, result) | ||
|
||
elif {"*", "/"} & exp_set: | ||
oper_idx: int = min(get_op_index(exp_oper, '*', exp_set), | ||
get_op_index(exp_oper, '/', exp_set)) | ||
op_a, op_b = map(int, (numb_exp[oper_idx], numb_exp[oper_idx + 1])) | ||
|
||
result: str = str(op_a * op_b if exp_oper[oper_idx] == '*' else op_a // op_b) | ||
|
||
for _ in range(2): | ||
numb_exp.pop(oper_idx) | ||
|
||
exp_oper.pop(oper_idx) | ||
numb_exp.insert(oper_idx, result) | ||
|
||
else: | ||
oper_idx: int = min(get_op_index(exp_oper, '+', exp_set), | ||
get_op_index(exp_oper, '-', exp_set)) | ||
op_a, op_b = map(int, (numb_exp[oper_idx], numb_exp[oper_idx + 1])) | ||
|
||
result: str = str(op_a + op_b if exp_oper[oper_idx] == '+' else op_a - op_b) | ||
|
||
for _ in range(2): | ||
numb_exp.pop(oper_idx) | ||
|
||
exp_oper.pop(oper_idx) | ||
numb_exp.insert(oper_idx, result) | ||
|
||
return numb_exp[0] | ||
|
||
|
||
def normalize_expression(expression: str) -> str: | ||
if not ("(" in expression and ")" in expression): | ||
return eval_flat_expression(expression) | ||
|
||
par_idx_1: int = expression.rindex('(') | ||
par_idx_2: int = par_idx_1 + expression[par_idx_1:].index(')') | ||
|
||
return normalize_expression(expression[:par_idx_1] +\ | ||
normalize_expression(expression[(par_idx_1 + 1):par_idx_2]) +\ | ||
expression[par_idx_2 + 1:]) | ||
|
||
|
||
def validate_expresssion(expression: str) -> bool: | ||
all_symbols_and_symbols: set[str] = set("()" + string.digits) | ||
elements_counter: dict[str, int] = collections.Counter(expression) | ||
|
||
if elements_counter['('] != elements_counter[')']: | ||
return False | ||
|
||
for idx, elem in enumerate(expression): | ||
if re.match(r'[1234567890]', elem) or re.match(r'[\(\)]', elem): | ||
continue | ||
|
||
if not re.match(r'[\+\-\*\/\^]', elem): | ||
return False | ||
|
||
try: | ||
if not {expression[idx - 1], expression[idx + 1]}.\ | ||
issubset(all_symbols_and_symbols): | ||
return False | ||
except IndexError: | ||
return False | ||
|
||
return True | ||
|
||
|
||
if __name__ == '__main__': | ||
file_path: str = os.path.join(os.path.dirname(__file__), 'd14.txt') | ||
|
||
try: | ||
expressions_file: TextIO = open(file_path, 'r') | ||
except FileNotFoundError as error: | ||
raise ValueError(f"Error: Could not open file \'{file_path}\'.") from error | ||
|
||
for line in expressions_file: | ||
line = line.rstrip().replace(' ', '') | ||
|
||
if not validate_expresssion(line): | ||
print("ERR SYNTAX") | ||
continue | ||
|
||
try: | ||
operation_result: str = normalize_expression(line) | ||
except ZeroDivisionError: | ||
operation_result: str = "ERR DIVBYZERO" | ||
|
||
print(operation_result) |