feat: MVP проекта закончено

This commit is contained in:
ElectronixTM
2025-03-16 01:41:59 +03:00
parent b044e908bb
commit 90f7569d7a
2 changed files with 82 additions and 9 deletions

View File

@ -4,13 +4,68 @@ this class applies markov algorightm to given string
""" """
from dataclasses import dataclass from dataclasses import dataclass
from collections import OrderedDict from typing import ClassVar
from rule import Rule, EMPTY_SYMBOL
@dataclass @dataclass
class Rulebook: class Rulebook:
rules: OrderedDict[str, str] MAX_DEPTH: ClassVar[int] = 100
rules: list[Rule]
def transform(self, string: str) -> str:
"""
Applies the next appropriate rule to given string. The
priority of rules is determined by their indexes in list
of rules. Lesser the index - higher the priority.
Return transformed string
"""
for _ in range(self.MAX_DEPTH):
rule = self.find_appropriate_rule(string)
if rule is None:
return string
string = self._apply_rule(rule, string)
if rule.is_blocking:
return string
raise ValueError("The amount of transformations exceeded "
f"{self.MAX_DEPTH}. You can change maximum "
"amount by setting class variable MAX_DEPTH,"
" but may be something wrong with your input")
def find_appropriate_rule(self, string) -> Rule | None:
"""
Searches for appropriate rule in rules list and if
found one returns it, otherwise returns None
"""
for rule in self.rules:
if self._is_rule_appropriate(rule, string):
return rule
def _apply_rule(self, rule: Rule, string: str) -> str:
"""
Tries to apply given rule to string. Doesn't check
wether the rule is appropriate or not. Inapplicability
leads to undefined behaviour
"""
if rule.operand == EMPTY_SYMBOL:
string = EMPTY_SYMBOL + string
string = (
string
.replace(rule.operand, rule.target, 1)
.replace(EMPTY_SYMBOL, '')
)
return string
def _is_rule_appropriate(self, rule: Rule, string: str) -> bool:
"""
Concrete realization of rule applicability check. Moved to separate
function mostly for extensibility purposes
"""
# Hardest part is always about empty set
if rule.operand == EMPTY_SYMBOL:
return True
return rule.operand in string
def __call__(self, string: str):
"""aplies rule to the given string"""
raise NotImplementedError("Sorry, we still don't know how to apply"
"algorithm to your string")

View File

@ -38,12 +38,31 @@ class RulesParser:
raise ValueError(f"Can't recognize transform symbol. " raise ValueError(f"Can't recognize transform symbol. "
f"\"{self.TRANSFORM}\" or \"{self.B_TRANSFORM}\"" f"\"{self.TRANSFORM}\" or \"{self.B_TRANSFORM}\""
f" expected, but \"{arrow}\" encountered") f" expected, but \"{arrow}\" encountered")
#optimising empty symbol
return Rule( return Rule(
operand=tokens[0], operand=self._optimise_empty(tokens[0]),
target=tokens[2], target=self._optimise_empty(tokens[2]),
is_blocking=is_blocking is_blocking=is_blocking
) )
def _optimise_empty(self, string: str) -> str:
"""
Empty symbol has meaning only while it's the only
symbol in the string (I hope i'm not wrong right now),
so all empty symbols can be optimised
Returns sting without EMPTY symbols if deleting them
is semantically possible, returns unchanges string if
nothing can be optimised
NOTE: right now contains naive implementation
"""
string = re.sub(self.EMPTY+'+', EMPTY_SYMBOL, string)
if re.fullmatch(self.EMPTY, string):
return string
return re.sub(self.EMPTY, '', string)
def _get_lines(self, src: str) -> list[str]: def _get_lines(self, src: str) -> list[str]:
""" """
Get cleaned lines only with rules to parse Get cleaned lines only with rules to parse
@ -65,5 +84,4 @@ class RulesParser:
Strips whitespaces at the end of lines Strips whitespaces at the end of lines
""" """
result = re.sub(r' +$', '', src, flags=re.M) result = re.sub(r' +$', '', src, flags=re.M)
# result = re.sub(r"\n+", r'\n', result)
return result return result