Скачиваний:
0
Добавлен:
15.04.2026
Размер:
5.81 Кб
Скачать
import collections
import itertools
import random


def generate(start: str, rules: list) -> str:
"""
Генерирует (порождает) слова языка, не допуская дубликатов слов
Может зациклиться, если rules не строит язык: {S -> S}, {F -> aFa} и др.
:param start: исходное слово (обычно: S)
:param rules: правила перевода
"""
# убираем пустой символ в исходном слове, если есть
start = start.replace('ε', '')
if start.islower(): # если нетерминальных символов нет, то возврат исходного слова
yield start
else: # если есть хотя бы один нетерминальный символ, то пробуем правила перевода
# убираем из правил перевода пустой символ, если есть
rules = [(from_.replace('ε', ''), to_.replace('ε', '')) for from_, to_ in rules]
q = collections.deque([start]) # очередь слов
generated_words = {start} # множество слов: и с терминальными, и с нетерминальными символами
while q: # q может стать пустым, если грамматика строит конечный язык
word = q.popleft() # получаем и удаляем первый элемент списка слов
for from_, to_ in rules: # перебираем все правила перевода from_ в to_
len_from_ = len(from_) # получаем длину from_
# перебираем все вхождения from_ в word
position = word.find(from_)
while position != -1:
# формируем новое слово, имея i вхождение from_ в word
new_word = word[:position] + to_ + word[position + len_from_:]
if new_word not in generated_words: # если слово не было ещё сгенерировано
generated_words.add(new_word) # добавляем в множество сгенерированных
if new_word.islower(): # если в new_word все символы терминальные
yield new_word # возвращаем new_word и продолжаем цикл
else: # если в new_word хотя бы один символ нетерминальный
q.append(new_word) # добавляем новое слово в очередь
position = word.find(from_, position + 1) # ищем следующее вхождение


def generate_all(start: str, rules: list, max_words: int) -> list:
"""
Генерирует (порождает) max_words слов языка
Может зациклиться, если rules не строит язык: {S -> S}, {F -> aFa} и др.
:param start: исходное слово (обычно: S)
:param rules: правила перевода
:param max_words: максимальное число слов языка
:return: список max_words слов языка
"""
return list(itertools.islice(generate(start, rules), max_words))


def generate_any(start: str, rules: list, max_words: int) -> list:
"""
Генерирует (порождает) max_words слов языка и возвращает любое из них
Может зациклиться, если rules не строит язык: {S -> S}, {F -> aFa} и др.
:param start: исходное слово (обычно: S)
:param rules: правила перевода
:param max_words: максимальное число слов языка
:return: любое из max_words слов языка
"""
return random.choice(generate_all(start, rules, max_words))




def main():
# Правила перевода
v_rules = [
# Вариант 1
[
('S', 'AA'),
('A', 'aAb'),
('A', 'ab')
],
# Вариант 2
[
('S', 'aSb'),
('S', 'cFc'),
('F', 'cFc'),
('F', 'ε')
],
# Вариант 3
[
('S', 'aF'),
('F', 'Sb'),
('F', 'Fb'),
('F', 'b')
],
# Вариант 4
[
('S', 'AA'), ('A', 'ab'),
('A', 'aBb'), ('B', 'ab'),
('B', 'aCb'), ('C', 'ab'),
('C', 'aDb'), ('D', 'ab')
],
# Вариант 5
[
('S', 'aaA'), ('A', 'a'),
('A', 'bbB'), ('B', 'b'),
('B', 'ccC'), ('C', 'c'),
('C', 'dD'), ('D', 'd')
]
]
start = 'S'
max_words = 50
for n, rules in enumerate(v_rules, 1):
print(f"{n} вариант")
# Генерация максимум max_words слов языка
words = generate_all(start, rules, max_words)
n_words = len(words)
print(f'Слова языка ({n_words}):', words)
# Генерация максимум max_words слов языка и возврат любого из них
any_word = generate_any(start, rules, max_words)
print(f'Любое из слов языка (до {n_words}):', any_word, end='\n\n')


if __name__ == '__main__':
main()

Соседние файлы в папке Programs