Skip to content

Commit

Permalink
feat: Conclusão do desafio 10 - @JamesStewart-314 (#1158)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesStewart-314 authored Dec 4, 2024
1 parent 24bac64 commit 4ce2d67
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 0 deletions.
1 change: 1 addition & 0 deletions desafio-10/JamesStewart-314/python/.valid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
152dc0886201ba0a2d0d8ea410f004b4b
34 changes: 34 additions & 0 deletions desafio-10/JamesStewart-314/python/README.md
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.
138 changes: 138 additions & 0 deletions desafio-10/JamesStewart-314/python/solution.py
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"))

0 comments on commit 4ce2d67

Please sign in to comment.