Генерация случайной строки
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import random
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
@@ -316,3 +317,61 @@ class Grammar:
|
||||
)
|
||||
|
||||
return rules_applied
|
||||
|
||||
def generate(self, symbol: str | None = None) -> tuple[list[str], list[int]]:
|
||||
"""Генерирует предложение по заданной грамматике. Возвращает список терминалов
|
||||
и список номеров применённых правил."""
|
||||
|
||||
if symbol is None:
|
||||
return self.generate(self.start_symbol)
|
||||
|
||||
# Если символ - терминал, возвращаем его
|
||||
if symbol not in self.productions:
|
||||
return [symbol], []
|
||||
|
||||
# Выбираем случайное правило для нетерминала
|
||||
rules = self.productions[symbol]
|
||||
chosen_rule = random.choice(rules)
|
||||
|
||||
# Получаем номер выбранного правила
|
||||
rule_number = self.rule_numbers[(symbol, tuple(chosen_rule))]
|
||||
|
||||
# Инициализируем результаты
|
||||
terminals = []
|
||||
rule_numbers = [rule_number]
|
||||
|
||||
# Разворачиваем каждый символ в правой части правила
|
||||
for s in chosen_rule:
|
||||
sub_terminals, sub_rules = self.generate(s)
|
||||
terminals.extend(sub_terminals)
|
||||
rule_numbers.extend(sub_rules)
|
||||
|
||||
return terminals, rule_numbers
|
||||
|
||||
def generate_derivation_steps(self, rule_numbers: list[int]) -> list[str]:
|
||||
"""Преобразует список номеров правил в последовательность шагов вывода.
|
||||
Возвращает список строк, представляющих каждый шаг вывода."""
|
||||
|
||||
# Получаем соответствие между номерами правил и самими правилами
|
||||
rule_details = {num: rule for rule, num in self.rule_numbers.items()}
|
||||
|
||||
# Начинаем с начального символа
|
||||
current = self.start_symbol
|
||||
steps = [current]
|
||||
|
||||
# Применяем каждое правило по порядку
|
||||
for rule_num in rule_numbers:
|
||||
if rule_num in rule_details:
|
||||
non_terminal, replacement = rule_details[rule_num]
|
||||
|
||||
# Находим первое вхождение нетерминала и заменяем его
|
||||
words = current.split()
|
||||
for i, word in enumerate(words):
|
||||
if word == non_terminal:
|
||||
words[i : i + 1] = replacement
|
||||
break
|
||||
|
||||
current = " ".join(words)
|
||||
steps.append(current)
|
||||
|
||||
return steps
|
||||
|
||||
Reference in New Issue
Block a user