Скачиваний:
0
Добавлен:
15.04.2026
Размер:
6 Кб
Скачать
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