This commit is contained in:
Maxim Slipenko 2021-09-15 22:39:37 +03:00
commit 1889c660a6
8 changed files with 323 additions and 0 deletions

138
.gitignore vendored Normal file
View File

@ -0,0 +1,138 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"python.linting.enabled": true
}

16
setup.py Normal file
View File

@ -0,0 +1,16 @@
from setuptools import setup
setup(
name='turinglab',
version='0.1.0',
author='Maxim Slipenko',
packages=['turinglab'],
install_requires = [
'python-docx'
],
entry_points = {
'console_scripts': [
'turinglab = turinglab.__main__:main'
]
}
)

0
turinglab/__init__.py Normal file
View File

23
turinglab/__main__.py Normal file
View File

@ -0,0 +1,23 @@
import sys
from turinglab.input import from_tur
from turinglab.emulator import Emulator
from turinglab.output import to_docx
def main():
tur, input_string, docx = sys.argv[1:]
[program,_,_] = from_tur(tur)
tm = Emulator(program, input_string)
data = [tm.info()]
while not tm.stopped:
tm.step()
data.append(tm.info())
to_docx(docx, data)
if __name__ == '__main__':
main()

49
turinglab/emulator.py Normal file
View File

@ -0,0 +1,49 @@
from collections import defaultdict
class Emulator():
'''
A class used to emulate an Turing machine
'''
def __init__(self, instructions, input_string: str = '', blank_symbol: chr = 'λ'):
self.head = 0
self.current_state = 0
self.blank_symbol = blank_symbol
self.instructions = instructions
self.stopped = False
self.tape = defaultdict(lambda: self.blank_symbol, dict(enumerate(input_string)))
def step(self):
if self.stopped == True:
raise RuntimeError('Turing machine is stopped!')
symbol = self.tape[self.head]
try:
symbol, direction, state = self.instructions[self.current_state][symbol]
self.tape[self.head] = symbol
self.current_state = state
self.head += 1 if direction == '>' else -1
self.tape[self.head] = self.tape[self.head]
if self.head < 0:
self.tape = defaultdict(lambda: self.blank_symbol, (sorted(self.tape.items())))
if self.current_state == -1:
self.stopped = True
except:
self.stopped = True
def info(self):
return [self.head, self.current_state, defaultdict(lambda: self.blank_symbol, self.tape)]

49
turinglab/input.py Normal file
View File

@ -0,0 +1,49 @@
import csv
import pprint
def from_tur(filename):
f = open(filename, "rb")
raw = []
byte = f.read(1)
while byte:
raw.append(byte)
byte = f.read(1)
indx = [0]
empty = [b'\x00', b'\x00', b'\x00']
for i in range(len(raw) - 2):
if raw[i:i+3] == empty:
indx.append(i)
indx.append(i+3)
data = []
for i in range(1, len(indx)):
packet = raw[indx[i - 1]:indx[i]]
if packet != empty:
data.append(packet)
task = b''.join(data[1]).decode('cp1251')
description = b''.join(data[4]).decode('cp1251')
solution = b''.join(data[3][:-2]).decode('cp1251')
solution = list(csv.reader(solution.split('\r\n'), delimiter='\t'))
header = solution[:1][0][1:]
solution_dict = [dict() for x in range(len(header))]
for x in solution[1:]:
symbol = x[0] if x[0] != ' ' else 'λ'
for (i, action) in enumerate(x[1:]):
action = list(action)
if len(action) == 0:
continue
if action[0] == '_':
action[0] = 'λ'
action[2] = int(action[2]) - 1
solution_dict[i][symbol] = action
return solution_dict, task, description

45
turinglab/output.py Normal file
View File

@ -0,0 +1,45 @@
from docx import Document
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Pt
from docx.enum.text import WD_LINE_SPACING
def to_docx(filename, data):
document = Document()
section = document.sections[0]
sectPr = section._sectPr
cols = sectPr.xpath('./w:cols')[0]
cols.set(qn('w:num'),'2')
style = document.styles['Normal']
font = style.font
font.name = 'Times New Roman'
font.size = Pt(14)
for i in range(len(data)):
p = document.add_paragraph('K')
p.paragraph_format.space_after = Pt(0)
p.paragraph_format.space_before = Pt(0)
p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.DOUBLE
index_text = p.add_run(str(i))
index_text.font.subscript = True
p.add_run(': ')
head, state, tape = data[i]
offset = list(tape.keys())[0]
head -= offset
tape_str = ''.join(tape.values())
p.add_run(tape_str[:head].lstrip('λ') + 'q')
index_text = p.add_run(str('z' if state == -1 else state))
index_text.font.subscript = True
p.add_run(tape_str[head] + tape_str[head + 1:].rstrip('λ'))
document.save(filename)