make big changes
This commit is contained in:
parent
7720a2a621
commit
3c4bcfdb72
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -1,8 +1,10 @@
|
|||||||
{
|
{
|
||||||
"python.linting.enabled": true,
|
"python.linting.enabled": true,
|
||||||
|
"python.linting.pycodestyleEnabled": true,
|
||||||
"python.testing.pytestArgs": [
|
"python.testing.pytestArgs": [
|
||||||
"tests"
|
"tests"
|
||||||
],
|
],
|
||||||
"python.testing.unittestEnabled": false,
|
"python.testing.unittestEnabled": false,
|
||||||
"python.testing.pytestEnabled": true,
|
"python.testing.pytestEnabled": true,
|
||||||
|
|
||||||
}
|
}
|
11
setup.py
11
setup.py
@ -6,12 +6,15 @@ setup(
|
|||||||
setup_requires=['setuptools_scm'],
|
setup_requires=['setuptools_scm'],
|
||||||
author='Maxim Slipenko',
|
author='Maxim Slipenko',
|
||||||
packages=['turinglab'],
|
packages=['turinglab'],
|
||||||
install_requires = [
|
install_requires=[
|
||||||
'python-docx'
|
'python-docx',
|
||||||
|
'pydot',
|
||||||
|
'requests',
|
||||||
|
'sortedcontainers'
|
||||||
],
|
],
|
||||||
entry_points = {
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'turinglab = turinglab.__main__:main'
|
'turinglab = turinglab.__main__:main'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,35 +1,39 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from turinglab.image import get_image
|
# from turinglab.image import get_image
|
||||||
from turinglab.input import from_file
|
from turinglab.input import from_file
|
||||||
from turinglab.emulator import Emulator
|
from turinglab.emulator import Emulator
|
||||||
from turinglab.output import to_docx
|
from turinglab.output import output
|
||||||
|
|
||||||
|
|
||||||
def get_parser() -> ArgumentParser:
|
def get_parser() -> ArgumentParser:
|
||||||
parser = ArgumentParser()
|
parser = ArgumentParser()
|
||||||
parser.add_argument("input_file", type=str, help="Path to file with program",)
|
parser.add_argument("input_file", type=str,
|
||||||
|
help="Path to file with program",)
|
||||||
parser.add_argument("output_dir", type=str, help="Output dir")
|
parser.add_argument("output_dir", type=str, help="Output dir")
|
||||||
parser.add_argument('-t','--tests', nargs='+', type=str, help='List of input strings for tests')
|
parser.add_argument("-t", '--tests', nargs='+', type=str,
|
||||||
parser.add_argument('-e','--empty-character', type=str, help='Empty character')
|
help='List of input strings for tests')
|
||||||
parser.add_argument('-f','--force', default=False, action='store_true', help='Force rewrite output dir')
|
parser.add_argument('-e', '--empty-character',
|
||||||
|
type=str, help='Empty character')
|
||||||
|
parser.add_argument('-f', '--force', default=False,
|
||||||
|
action='store_true', help='Force rewrite output dir')
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = get_parser()
|
parser = get_parser()
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
program = from_file(args.input_file)
|
program = from_file(args.input_file)
|
||||||
|
|
||||||
if args.force == False and os.path.exists(args.output_dir):
|
if args.force is False and os.path.exists(args.output_dir):
|
||||||
print('Directory already exists!')
|
print('Directory already exists!')
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
os.makedirs(args.output_dir, exist_ok=True)
|
os.makedirs(args.output_dir, exist_ok=True)
|
||||||
|
|
||||||
test_data = []
|
tests = []
|
||||||
|
|
||||||
for test in args.tests:
|
for test in args.tests:
|
||||||
test = test.replace(args.empty_character, 'λ')
|
test = test.replace(args.empty_character, 'λ')
|
||||||
@ -42,11 +46,13 @@ def main():
|
|||||||
tm.step()
|
tm.step()
|
||||||
data.append(tm.info())
|
data.append(tm.info())
|
||||||
|
|
||||||
test_data.append(data)
|
tests.append(data)
|
||||||
|
|
||||||
|
output(args.output_dir, program, tests)
|
||||||
|
|
||||||
|
# to_docx(os.path.join(args.output_dir, 'report.docx'), program, test_data)
|
||||||
|
# get_image(os.path.join(args.output_dir, 'graph'), program)
|
||||||
|
|
||||||
to_docx(os.path.join(args.output_dir, 'report.docx'), program, test_data)
|
|
||||||
get_image(os.path.join(args.output_dir, 'graph'), program)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
@ -1,54 +1,135 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from sortedcontainers import SortedDict
|
||||||
|
from copy import copy, deepcopy
|
||||||
|
from enum import IntEnum
|
||||||
|
|
||||||
DIRECTIONS = {
|
|
||||||
'>': 1,
|
class Movemement(IntEnum):
|
||||||
'<': -1,
|
R = 1
|
||||||
'.': 0
|
L = -1
|
||||||
}
|
E = 0
|
||||||
|
|
||||||
|
|
||||||
|
class Action:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
state,
|
||||||
|
symbol: chr,
|
||||||
|
movement: Movemement
|
||||||
|
) -> None:
|
||||||
|
self.state = state
|
||||||
|
self.symbol = symbol
|
||||||
|
self.movement = movement
|
||||||
|
|
||||||
|
|
||||||
|
class Program:
|
||||||
|
data = dict()
|
||||||
|
|
||||||
|
state_count = 0
|
||||||
|
symbol_count = 0
|
||||||
|
symbol_dict = dict()
|
||||||
|
|
||||||
|
blank_symbol = 'λ'
|
||||||
|
|
||||||
|
def __init__(self, blank_symbol: chr = 'λ') -> None:
|
||||||
|
self.blank_symbol = blank_symbol
|
||||||
|
|
||||||
|
def is_blank(self, symbol) -> bool:
|
||||||
|
return symbol == self.blank_symbol
|
||||||
|
|
||||||
|
def set(self, state, symbol, action) -> None:
|
||||||
|
if state not in self.data:
|
||||||
|
self.data[state] = dict()
|
||||||
|
self.state_count += 1
|
||||||
|
|
||||||
|
self.symbol_dict[symbol] = None
|
||||||
|
self.data[state][symbol] = action
|
||||||
|
|
||||||
|
def get(self, state, symbol) -> Action or None:
|
||||||
|
if symbol not in self.data[state]:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self.data[state][symbol]
|
||||||
|
|
||||||
|
def get_symbols(self):
|
||||||
|
return list(self.symbol_dict.keys())
|
||||||
|
|
||||||
|
|
||||||
class Emulator():
|
class Emulator():
|
||||||
'''
|
"""
|
||||||
A class used to emulate an Turing machine
|
A class used to emulate an Turing machine
|
||||||
'''
|
"""
|
||||||
|
|
||||||
def __init__(self, instructions, input_string: str = '', blank_symbol: chr = 'λ'):
|
class Tape:
|
||||||
|
|
||||||
|
l_index = 0
|
||||||
|
r_index = 0
|
||||||
|
|
||||||
|
def __init__(self, input_string: str, blank_symbol: str) -> None:
|
||||||
|
self.tape = SortedDict(dict(enumerate(input_string)))
|
||||||
|
self.blank_symbol = blank_symbol
|
||||||
|
|
||||||
|
r_index = len(input_string)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __deepcopy__(self, memo):
|
||||||
|
id_self = id(self)
|
||||||
|
_copy = memo.get(id_self)
|
||||||
|
if _copy is None:
|
||||||
|
_copy = type(self)('', self.blank_symbol)
|
||||||
|
|
||||||
|
_copy.tape = deepcopy(self.tape)
|
||||||
|
_copy.blank_symbol = self.blank_symbol
|
||||||
|
_copy.l_index = self.l_index
|
||||||
|
_copy.r_index = self.r_index
|
||||||
|
|
||||||
|
memo[id_self] = _copy
|
||||||
|
return _copy
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self.tape[key] = value
|
||||||
|
self.l_index = min(self.l_index, key)
|
||||||
|
self.r_index = max(self.r_index, key)
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
if key not in self.tape:
|
||||||
|
return self.blank_symbol
|
||||||
|
|
||||||
|
return self.tape[key]
|
||||||
|
|
||||||
|
def values(self):
|
||||||
|
return self.tape.values()
|
||||||
|
|
||||||
|
def __init__(self, program: Program, input_string: str = ''):
|
||||||
self.head = 0
|
self.head = 0
|
||||||
self.current_state = 0
|
self.state = 0
|
||||||
|
|
||||||
self.blank_symbol = blank_symbol
|
|
||||||
self.instructions = instructions
|
|
||||||
|
|
||||||
self.stopped = False
|
self.stopped = False
|
||||||
|
|
||||||
self.tape = defaultdict(lambda: self.blank_symbol, dict(enumerate(input_string)))
|
self.program = program
|
||||||
|
self.tape = Emulator.Tape(input_string, program.blank_symbol)
|
||||||
|
|
||||||
def step(self):
|
def step(self):
|
||||||
if self.stopped == True:
|
if self.stopped is True:
|
||||||
raise RuntimeError('Turing machine is stopped!')
|
raise RuntimeError('Turing machine is stopped!')
|
||||||
|
|
||||||
symbol = self.tape[self.head]
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
symbol, direction, state = self.instructions[symbol][self.current_state]
|
action = self.program.get(self.state, self.tape[self.head])
|
||||||
self.tape[self.head] = symbol
|
|
||||||
|
|
||||||
self.current_state = state
|
self.tape[self.head] = action.symbol
|
||||||
self.head += DIRECTIONS[direction]
|
self.state = action.state
|
||||||
|
self.head += int(action.movement)
|
||||||
self.tape[self.head] = self.tape[self.head]
|
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:
|
if self.state == -1:
|
||||||
self.stopped = True
|
self.stopped = True
|
||||||
|
|
||||||
except:
|
except Exception as err:
|
||||||
self.stopped = True
|
self.stopped = True
|
||||||
|
print('Error', err)
|
||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
return [self.head, self.current_state, defaultdict(lambda: self.blank_symbol, self.tape)]
|
return [
|
||||||
|
self.head,
|
||||||
|
self.state,
|
||||||
|
deepcopy(self.tape),
|
||||||
|
]
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
import pydot
|
|
||||||
import requests
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
def get_image(filename, program):
|
|
||||||
g = pydot.Dot('my_graph', nodesep=0.5)
|
|
||||||
g.set_node_defaults(
|
|
||||||
width='1.5',
|
|
||||||
fontsize='18',
|
|
||||||
shape='circle'
|
|
||||||
)
|
|
||||||
|
|
||||||
rows = 0
|
|
||||||
cols = len(program.keys())
|
|
||||||
|
|
||||||
for x in program.keys():
|
|
||||||
if len(list(program[x].keys())) == 0:
|
|
||||||
continue
|
|
||||||
rows = max(list(program[x].keys())[-1] + 1, rows)
|
|
||||||
|
|
||||||
program_table = [None] * rows
|
|
||||||
|
|
||||||
for i in range(rows):
|
|
||||||
program_table[i] = [None] * cols
|
|
||||||
|
|
||||||
symbols = [None] * cols
|
|
||||||
|
|
||||||
for j, (symbol, value) in enumerate(program.items()):
|
|
||||||
symbols[j] = symbol
|
|
||||||
for i, (state, action) in enumerate(value.items()):
|
|
||||||
program_table[state][j] = action
|
|
||||||
|
|
||||||
g.add_node(pydot.Node(f'gz', label='<g<SUB>z</SUB>>', shape='circle'))
|
|
||||||
|
|
||||||
for i in range(rows):
|
|
||||||
g.add_node(pydot.Node(f'g{i}', label=f'<g<SUB>{i}</SUB>>', shape='circle'))
|
|
||||||
for j in range(cols):
|
|
||||||
action = program_table[i][j]
|
|
||||||
if action is None: continue
|
|
||||||
|
|
||||||
symbol, direction, state = action
|
|
||||||
label = symbols[j] + '/' + symbol + '/' + ('R' if direction == '>' else 'L')
|
|
||||||
src = f'g{i}'
|
|
||||||
dst = f'g{"z" if state == -1 else state}'
|
|
||||||
if src == dst:
|
|
||||||
src = src + ':ne'
|
|
||||||
dst = dst + ':se'
|
|
||||||
g.add_edge(pydot.Edge(src, dst, label = label))
|
|
||||||
|
|
||||||
|
|
||||||
g.write_raw(f'{filename}.dot', encoding='utf-8')
|
|
||||||
|
|
||||||
try:
|
|
||||||
g.write_svg(f'{filename}.svg', encoding='utf-8')
|
|
||||||
except Exception:
|
|
||||||
output_raw_dot = g.to_string()
|
|
||||||
img_data = requests.get("https://quickchart.io/graphviz?graph=" + output_raw_dot).content
|
|
||||||
with open(f'{filename}_quickchart.svg', 'wb') as handler:
|
|
||||||
handler.write(img_data)
|
|
||||||
|
|
@ -1,78 +1,38 @@
|
|||||||
import csv
|
|
||||||
import re
|
import re
|
||||||
|
from turinglab.emulator import Program, Movemement, Action
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
def from_file(filename: str):
|
def from_file(filename: str):
|
||||||
|
|
||||||
f = open(filename, "r")
|
f = open(filename, "r")
|
||||||
|
|
||||||
program = dict()
|
program = Program(blank_symbol="_")
|
||||||
|
|
||||||
|
# program = dict()
|
||||||
|
|
||||||
for line in f:
|
for line in f:
|
||||||
symbol, *actions = line.replace("\n", "").split('\t')
|
symbol, *actions = line.replace("\n", "").split('\t')
|
||||||
|
|
||||||
if symbol == " ":
|
if symbol == " ":
|
||||||
symbol = "λ"
|
symbol = "_"
|
||||||
|
|
||||||
program[symbol] = dict()
|
|
||||||
|
|
||||||
for i, action in enumerate(actions):
|
for i, action in enumerate(actions):
|
||||||
if not action:
|
if not action:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
new_symbol, direction, new_state = re.split('([<|>|.])', action)
|
new_symbol, direction, new_state = re.split('([<|>|.])', action)
|
||||||
|
|
||||||
if new_symbol == "_":
|
|
||||||
new_symbol = 'λ'
|
|
||||||
new_state = int(new_state) - 1
|
new_state = int(new_state) - 1
|
||||||
|
|
||||||
program[symbol][i] = ([new_symbol, direction, new_state])
|
movement = {
|
||||||
|
'>': Movemement.R,
|
||||||
|
'.': Movemement.E,
|
||||||
|
'<': Movemement.L
|
||||||
|
}[direction]
|
||||||
|
|
||||||
|
program.set(i, symbol, Action(new_state, new_symbol, movement))
|
||||||
|
|
||||||
|
# program[symbol][i] = ([new_symbol, direction, new_state])
|
||||||
|
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
return program
|
return program
|
||||||
|
@ -1,107 +1,123 @@
|
|||||||
from turinglab.image import get_image
|
import pydot
|
||||||
|
import requests
|
||||||
|
import shutil
|
||||||
|
from os import path
|
||||||
from docx import Document
|
from docx import Document
|
||||||
from docx.oxml import OxmlElement
|
from docx.shared import Pt
|
||||||
from docx.oxml.ns import qn
|
|
||||||
from docx.shared import Pt, Inches
|
|
||||||
from docx.enum.text import WD_LINE_SPACING
|
from docx.enum.text import WD_LINE_SPACING
|
||||||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||||
|
from turinglab.emulator import Movemement, Program
|
||||||
|
|
||||||
def add_state(p, state):
|
|
||||||
p.add_run('q')
|
|
||||||
index_text = p.add_run(str('z' if state == -1 else state))
|
|
||||||
index_text.font.subscript = True
|
|
||||||
|
|
||||||
def create_paragraph(document):
|
def output(
|
||||||
p = document.add_paragraph()
|
directory,
|
||||||
style_paragraph(p)
|
program: Program,
|
||||||
return p
|
tests,
|
||||||
|
docx_name="report",
|
||||||
|
graph_name="graph"
|
||||||
|
):
|
||||||
|
"""Create output of a program and tests. It's includes a docx file with
|
||||||
|
a 'command system', 'functional table' and tests.
|
||||||
|
"""
|
||||||
|
|
||||||
def style_paragraph(p):
|
def create_paragraph(document, text=""):
|
||||||
p.paragraph_format.space_after = Pt(0)
|
p = document.add_paragraph(text)
|
||||||
p.paragraph_format.space_before = Pt(0)
|
style_paragraph(p)
|
||||||
p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
|
return p
|
||||||
|
|
||||||
|
def style_paragraph(p):
|
||||||
|
p.paragraph_format.space_after = Pt(0)
|
||||||
|
p.paragraph_format.space_before = Pt(0)
|
||||||
|
p.paragraph_format.line_spacing_rule = WD_LINE_SPACING.ONE_POINT_FIVE
|
||||||
|
|
||||||
|
def state_index(state):
|
||||||
|
return str('z' if state == -1 else state)
|
||||||
|
|
||||||
|
def add_state(p, state):
|
||||||
|
p.add_run('q')
|
||||||
|
index_text = p.add_run(state_index(state))
|
||||||
|
index_text.font.subscript = True
|
||||||
|
|
||||||
|
def get_symbol(x):
|
||||||
|
return x if program.is_blank(x) is False else 'λ'
|
||||||
|
|
||||||
def to_docx(filename, program, data):
|
|
||||||
document = Document()
|
document = Document()
|
||||||
|
|
||||||
style = document.styles['Normal']
|
|
||||||
font = style.font
|
|
||||||
font.name = 'Times New Roman'
|
|
||||||
font.size = Pt(14)
|
|
||||||
|
|
||||||
rows = 0
|
#
|
||||||
cols = len(program.keys())
|
# Command system
|
||||||
|
#
|
||||||
|
create_paragraph(document, "Система команд:")
|
||||||
|
|
||||||
for x in program.keys():
|
symbols = program.get_symbols()
|
||||||
if len(list(program[x].keys())) == 0:
|
|
||||||
continue
|
|
||||||
rows = max(list(program[x].keys())[-1] + 1, rows)
|
|
||||||
|
|
||||||
program_table = [None] * rows
|
cols = len(symbols)
|
||||||
|
rows = program.state_count
|
||||||
|
program_table = [[[None] for n in range(cols)] for m in range(rows)]
|
||||||
|
|
||||||
for i in range(rows):
|
for i in range(rows):
|
||||||
program_table[i] = [None] * cols
|
for j in range(cols):
|
||||||
|
program_table[i][j] = program.get(i, symbols[j])
|
||||||
|
|
||||||
symbols = [None] * cols
|
|
||||||
|
|
||||||
for j, (symbol, value) in enumerate(program.items()):
|
|
||||||
symbols[j] = symbol
|
|
||||||
for i, (state, action) in enumerate(value.items()):
|
|
||||||
program_table[state][j] = action
|
|
||||||
|
|
||||||
for i in range(rows):
|
for i in range(rows):
|
||||||
for j in range(cols):
|
for j in range(cols):
|
||||||
action = program_table[i][j]
|
action = program_table[i][j]
|
||||||
if action is None: continue
|
if action is None:
|
||||||
|
continue
|
||||||
|
|
||||||
p = create_paragraph(document)
|
p = create_paragraph(document)
|
||||||
add_state(p, i)
|
add_state(p, i)
|
||||||
|
|
||||||
symbol, direction, state = action
|
movement = Movemement(action.movement).name
|
||||||
|
|
||||||
p.add_run(symbols[j] + ' → ')
|
p.add_run(get_symbol(symbols[j]) + ' → ')
|
||||||
add_state(p, state)
|
add_state(p, action.state)
|
||||||
p.add_run(symbol + ('R' if direction == '>' else 'L'))
|
p.add_run(get_symbol(action.symbol) + movement)
|
||||||
|
|
||||||
|
#
|
||||||
p = create_paragraph(document)
|
# Functional table
|
||||||
|
#
|
||||||
|
create_paragraph(document)
|
||||||
|
create_paragraph(document, "Функциональная таблица:")
|
||||||
|
|
||||||
table = document.add_table(rows + 1, cols + 1)
|
table = document.add_table(rows + 1, cols + 1)
|
||||||
table.style = 'Table Grid'
|
table.style = 'Table Grid'
|
||||||
table.autofit = True
|
table.autofit = True
|
||||||
table.allow_autofit = True
|
table.allow_autofit = True
|
||||||
|
|
||||||
for i in range(0, rows):
|
for i in range(0, rows):
|
||||||
p = table.rows[i + 1].cells[0].paragraphs[0]
|
p = table.rows[i + 1].cells[0].paragraphs[0]
|
||||||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||||
style_paragraph(p)
|
style_paragraph(p)
|
||||||
add_state(p, i)
|
add_state(p, i)
|
||||||
|
|
||||||
for i, x in enumerate(program.keys()):
|
for i, x in enumerate(symbols):
|
||||||
p = table.rows[0].cells[i + 1].paragraphs[0]
|
p = table.rows[0].cells[i + 1].paragraphs[0]
|
||||||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||||
style_paragraph(p)
|
style_paragraph(p)
|
||||||
p.add_run(x)
|
p.add_run(get_symbol(x))
|
||||||
|
|
||||||
for i in range(rows):
|
for i in range(rows):
|
||||||
for j in range(cols):
|
for j in range(cols):
|
||||||
action = program_table[i][j]
|
action = program_table[i][j]
|
||||||
if action is None: continue
|
if action is None:
|
||||||
|
continue
|
||||||
|
|
||||||
p = table.rows[i + 1].cells[j + 1].paragraphs[0]
|
p = table.rows[i + 1].cells[j + 1].paragraphs[0]
|
||||||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||||
style_paragraph(p)
|
style_paragraph(p)
|
||||||
|
|
||||||
symbol, direction, state = action
|
movement = Movemement(action.movement).name
|
||||||
add_state(p, state)
|
add_state(p, action.state)
|
||||||
p.add_run(symbol)
|
p.add_run(get_symbol(action.symbol) + movement)
|
||||||
p.add_run('R' if direction == '>' else 'L')
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tests
|
||||||
|
#
|
||||||
p = create_paragraph(document)
|
p = create_paragraph(document)
|
||||||
|
|
||||||
for i, test in enumerate(data):
|
for i, test in enumerate(tests):
|
||||||
p = create_paragraph(document)
|
p = create_paragraph(document)
|
||||||
p.add_run(f'Test {i + 1}:')
|
p.add_run(f'Тест {i + 1}')
|
||||||
|
|
||||||
for j, data in enumerate(test):
|
for j, data in enumerate(test):
|
||||||
p = create_paragraph(document)
|
p = create_paragraph(document)
|
||||||
@ -113,15 +129,76 @@ def to_docx(filename, program, data):
|
|||||||
p.add_run(': ')
|
p.add_run(': ')
|
||||||
|
|
||||||
head, state, tape = data
|
head, state, tape = data
|
||||||
offset = list(tape.keys())[0]
|
|
||||||
head -= offset
|
|
||||||
tape_str = ''.join(tape.values())
|
tape_str = ''.join(tape.values())
|
||||||
|
head -= tape.l_index
|
||||||
|
|
||||||
p.add_run(tape_str[:head].lstrip('λ') + 'q')
|
left_str = tape_str[:head].lstrip(program.blank_symbol)
|
||||||
|
left_str = left_str.replace(program.blank_symbol, 'λ')
|
||||||
|
right_str = tape_str[head + 1:].rstrip(program.blank_symbol)
|
||||||
|
right_str = right_str.replace(program.blank_symbol, 'λ')
|
||||||
|
|
||||||
index_text = p.add_run(str('z' if state == -1 else state))
|
p.add_run(left_str)
|
||||||
index_text.font.subscript = True
|
add_state(p, state)
|
||||||
|
p.add_run(get_symbol(tape_str[head]))
|
||||||
|
p.add_run(right_str)
|
||||||
|
|
||||||
p.add_run(tape_str[head] + tape_str[head + 1:].rstrip('λ'))
|
document.save(path.join(directory, docx_name + ".docx"))
|
||||||
|
|
||||||
document.save(filename)
|
#
|
||||||
|
# Image
|
||||||
|
#
|
||||||
|
|
||||||
|
g = pydot.Dot("mygraph", nodesep=0.75)
|
||||||
|
|
||||||
|
g.set_node_defaults(
|
||||||
|
width='1.5',
|
||||||
|
fontsize='40',
|
||||||
|
shape='circle'
|
||||||
|
)
|
||||||
|
g.set_edge_defaults(
|
||||||
|
fontsize='20'
|
||||||
|
)
|
||||||
|
|
||||||
|
end_node = pydot.Node(f'gz', label='<g<SUB>z</SUB>>', shape='circle')
|
||||||
|
g.add_node(end_node)
|
||||||
|
|
||||||
|
for i in range(rows):
|
||||||
|
node = pydot.Node(f'g{i}', label=f'<g<SUB>{i}</SUB>>', shape='circle')
|
||||||
|
g.add_node(node)
|
||||||
|
for j in range(cols):
|
||||||
|
action = program_table[i][j]
|
||||||
|
if action is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
movement = Movemement(action.movement).name
|
||||||
|
|
||||||
|
label = get_symbol(symbols[j]) +\
|
||||||
|
'/' + get_symbol(action.symbol) +\
|
||||||
|
'/' + movement
|
||||||
|
|
||||||
|
src = f'g{i}'
|
||||||
|
dst = f'g{state_index(action.state)}'
|
||||||
|
if src == dst:
|
||||||
|
src = src + ':ne'
|
||||||
|
dst = dst + ':se'
|
||||||
|
|
||||||
|
g.add_edge(pydot.Edge(src, dst, label=label))
|
||||||
|
|
||||||
|
dot_path = path.join(directory, f'{graph_name}.dot')
|
||||||
|
g.write_raw(dot_path, encoding='utf-8')
|
||||||
|
|
||||||
|
try:
|
||||||
|
svg_path = path.join(directory, f'{graph_name}.svg')
|
||||||
|
|
||||||
|
g.write_svg(svg_path, encoding='utf-8')
|
||||||
|
except Exception:
|
||||||
|
output_raw_dot = g.to_string()
|
||||||
|
img_data = requests.get(
|
||||||
|
"https://quickchart.io/graphviz?graph=" + output_raw_dot
|
||||||
|
).content
|
||||||
|
|
||||||
|
svg_path = path.join(directory, f'{graph_name}_quickchart.svg')
|
||||||
|
|
||||||
|
with open(svg_path, 'wb') as handler:
|
||||||
|
handler.write(img_data)
|
||||||
|
Loading…
Reference in New Issue
Block a user