-
Notifications
You must be signed in to change notification settings - Fork 265
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 10 - @JamesStewart-314 (#1158)
- Loading branch information
1 parent
24bac64
commit 4ce2d67
Showing
3 changed files
with
173 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 @@ | ||
152dc0886201ba0a2d0d8ea410f004b4b |
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,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 | ||
<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, 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. |
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,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")) |