From 4ce2d6788854d35c22ae33ddc2f585af98a77b1f Mon Sep 17 00:00:00 2001 From: Allber Fellype Soares Ferreira Date: Wed, 4 Dec 2024 02:51:37 -0300 Subject: [PATCH] =?UTF-8?q?feat:=20Conclus=C3=A3o=20do=20desafio=2010=20-?= =?UTF-8?q?=20@JamesStewart-314=20(#1158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- desafio-10/JamesStewart-314/python/.valid | 1 + desafio-10/JamesStewart-314/python/README.md | 34 +++++ .../JamesStewart-314/python/solution.py | 138 ++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 desafio-10/JamesStewart-314/python/.valid create mode 100644 desafio-10/JamesStewart-314/python/README.md create mode 100644 desafio-10/JamesStewart-314/python/solution.py diff --git a/desafio-10/JamesStewart-314/python/.valid b/desafio-10/JamesStewart-314/python/.valid new file mode 100644 index 000000000..5bf8db66d --- /dev/null +++ b/desafio-10/JamesStewart-314/python/.valid @@ -0,0 +1 @@ +152dc0886201ba0a2d0d8ea410f004b4b diff --git a/desafio-10/JamesStewart-314/python/README.md b/desafio-10/JamesStewart-314/python/README.md new file mode 100644 index 000000000..14af38f52 --- /dev/null +++ b/desafio-10/JamesStewart-314/python/README.md @@ -0,0 +1,34 @@ +# Desafio 10 - Turing Machine +![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: +Define-se como [Máquina de Turing](https://en.wikipedia.org/wiki/Turing_machine) uma +máquina programável de propósito geral capaz de realizar qualquer procedimento finito e +computável em uma fita seccionada por células. Este conceito foi concebido inicialmente +por [Alan Turing](https://pt.wikipedia.org/wiki/Alan_Turing) e possui profundas +implicações em diversos conceitos da ciência computacional, como por exemplo a abstração +de problemas diversos para código de programação. + +O objetivo deste projeto consiste em replicar parcialmente o comportamento de uma máquina +de turing em Python. As regras e entradas da máquina estarão explicitamente definidas em +arquivos distintos e o resultado do processamento de cada arquivo com suas respectivas +regras será exibida no terminal ao término da execução do programa. + +## 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 + Python.org + 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, abra o terminal de comando e navegue até o diretório contendo o arquivo +`"solution.py"`. Em seguida, digite `python solution.py` +e os resultados deverão ser impressos de maneira formatada na CLI. diff --git a/desafio-10/JamesStewart-314/python/solution.py b/desafio-10/JamesStewart-314/python/solution.py new file mode 100644 index 000000000..af3359e6d --- /dev/null +++ b/desafio-10/JamesStewart-314/python/solution.py @@ -0,0 +1,138 @@ +import os +from typing import TextIO + +class TurMach: + _direction_map: dict[str, int] = {'l': (-1), 'r': 1, '*': 0} + + def __init__(self) -> None: + self._turing_rules: dict[str, dict[str, tuple[str, str, str]]] = {} + self._tape_position: int = 0 + self._current_state: str = '0' + + def __repr__(self) -> str: + return f"{self.__class__.__name__}<{self._turing_rules}, "\ + f"{self._tape_position}, {self._current_state}>" + + @staticmethod + def _convert_symbol(old_symbol: str, new_symbol: str) -> str: + if new_symbol == '*': + return old_symbol + if new_symbol == '_': + return ' ' + return new_symbol + + def _restore_initial_state(self) -> None: + self._turing_rules.clear() + self._tape_position = 0 + self._current_state = '0' + + def _check_state(self, state: str | None = None) -> bool: + state = state if state is not None else self._current_state + return state in self._turing_rules + + def _check_symbol(self, symbol: str, state: str | None = None) -> bool: + state = state if state is not None else self._current_state + return symbol in self._turing_rules[state] + + def _check_exists_valid_rule(self) -> bool: + current_state_rule: bool = self._current_state in self._turing_rules + generic_state_rule: bool = '*' in self._turing_rules + + return current_state_rule or generic_state_rule + + def process_datafile(self, file_path: str) -> None: + try: + datafile_obj: TextIO = open(file_path, "r") + except FileNotFoundError as error: + raise Exception(f"Error: Could not open datafile \'{file_path}\'.") from error + + for data_line in datafile_obj: + self._restore_initial_state() + data_line: list[str] = data_line.rstrip().split(',') + turing_rules_file_path: str = os.path.join(os.path.dirname(file_path), data_line[0]) + + try: + turing_rules_file: TextIO = open(turing_rules_file_path, "r") + except FileNotFoundError as error: + raise Exception(f"Error: Could not open file \'{turing_rules_file_path}\'.")\ + from error + + for rule_line in turing_rules_file: + rule_line = rule_line.rstrip() + if not rule_line or rule_line[0] == ';': + continue + + try: + rule_line = rule_line[:rule_line.index(';')].rstrip() + except ValueError: + pass + + rule_line_splitted: list[str] = rule_line.split() + + self._turing_rules.setdefault(rule_line_splitted[0], {}).\ + setdefault(rule_line_splitted[1], rule_line_splitted[2:]) + + content_tape: list[str] = list(data_line[1]) + is_valid_result: bool = True + while True: + if not self._check_exists_valid_rule(): + is_valid_result = False + break + + symbols_map: dict[str, tuple[str, str, str]] + current_symbol: str = content_tape[self._tape_position].replace(' ', '_') + + if self._check_state() and self._check_symbol(current_symbol): + symbols_map = self._turing_rules[self._current_state] + elif self._check_state('*') and self._check_symbol(current_symbol, '*'): + symbols_map = self._turing_rules['*'] + elif self._check_state() and self._check_symbol('*'): + symbols_map = self._turing_rules[self._current_state] + elif self._check_state('*') and self._check_symbol('*', '*'): + symbols_map = self._turing_rules['*'] + else: + is_valid_result = False + break + + if not (current_symbol in symbols_map or '*' in symbols_map): + is_valid_result = False + break + + transformation: tuple[str, str, str] = symbols_map.get(current_symbol) or\ + symbols_map['*'] + content_tape[self._tape_position] = TurMach._convert_symbol(current_symbol, + transformation[0]) + + if (new_pos := TurMach._direction_map.get(transformation[1])) is None: + is_valid_result = False + break + + if new_pos == (-1) and self._tape_position == 0: + content_tape.insert(0, ' ') + elif new_pos == 1 and self._tape_position == len(content_tape) - 1: + content_tape.append(' ') + self._tape_position += 1 + else: + self._tape_position += new_pos + + if transformation[2].startswith('halt'): + break + + self._current_state = transformation[2] + + final_message: str = f"{data_line[0]},{data_line[1]}," + if is_valid_result: + final_message += f"{''.join(content_tape).strip()}" + else: + final_message += "ERR" + + print(final_message) + + self._restore_initial_state() + + return + + +if __name__ == '__main__': + machine: TurMach = TurMach() + machine.process_datafile(os.path.join(os.path.dirname(__file__), "datafile"))