Skip to content

Commit

Permalink
feat: Conclusão do Desafio 14 - @JamesStewart-314 (#1168)
Browse files Browse the repository at this point in the history
* 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
JamesStewart-314 and Allber Fellype authored Dec 16, 2024
1 parent 9e4df72 commit 86fe613
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
1 change: 1 addition & 0 deletions desafio-14/JamesStewart-314/python/.valid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
19c61202b5c41fa163e195175d0c061a1
55 changes: 55 additions & 0 deletions desafio-14/JamesStewart-314/python/README.md
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.
114 changes: 114 additions & 0 deletions desafio-14/JamesStewart-314/python/solution.py
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)

0 comments on commit 86fe613

Please sign in to comment.