Python: обнаружение шаблона букв без перебора всех возможных комбинаций

Приношу извинения за, возможно, не очень полезное название; Я не мог понять, как сформулировать эту проблему в одном предложении.

Я пытаюсь подсчитать, сколько «единиц» имеет слово в Python 3.10. Одна «единица» — это (C для согласной и V для гласной) либо CV, либо VC, либо C или V (последние две используются только тогда, когда невозможно составить пару). Например, «штука» будет состоять из трех единиц (pi-e-ce или pi-ec-e), «очередь» — из четырех единиц (qu-e-u-e), а «абажур» — из шести единиц (la-m-p-s-ha-de).

С чем я борюсь, так это с тем, как именно мне определить эти единицы, не перебирая каждую комбинацию каждой гласной и согласной для каждой пары букв. Было бы крайне неэффективно делать это с помощью итерации, но я не могу придумать ничего лучшего с моими текущими знаниями Python. Каким будет эффективный способ решения этой проблемы?

В качестве дополнительной (необязательной) проблемы: что, если ввести орграфы, например «gh» и «th»? В результате такие слова, как «бедро» (четыре единицы, t-hi-g-h), будут состоять только из двух единиц (thi-gh), но это также усложнит разработку.

Зачем вам перебирать каждую комбинацию? Почему бы просто не проверить, является ли одно гласным, а другое — согласным?

Andrew Yim 26.07.2024 01:31

Хотите ли вы найти ЛЮБОЙ результат или конкретный результат. Например, asian должно вернуть as-i-an или a-si-an?

Rodrigo Rodrigues 26.07.2024 01:59

@RodrigoRodrigues - похоже, речь идет больше о поиске «единиц», и в вашем примере в любом случае это 3 единицы.

OysterShucker 26.07.2024 02:01

в этом случае это так же просто, как подсчитать, сколько раз вы меняете гласную на согласную или наоборот. Просто повторите один раз, никаких комбинаций не требуется.

Rodrigo Rodrigues 26.07.2024 02:03

@RodrigoRodrigues - вы не можете просто посчитать переходы, потому что «CV» и «VC» — это единица измерения. Пример: «CVVVC» в вашем подсчете равен 2, но реальный счет равен 3. Мой ответ иллюстрирует 1 способ получить правильный счет. Я мог бы сделать это более прямолинейно, но я решил упростить понимание.

OysterShucker 26.07.2024 02:07
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
5
70
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Просто преобразуйте все в «V» или «C» соответственно в списке. Затем проверьте первые 2 буквы в цикле. Если это «CV» или «VC», откройте список и, несмотря ни на что, откройте его еще раз. Подсчитайте, сколько итераций потребуется, чтобы исчерпать список.

def units(word) -> int:
    word = ["V" if c in "aeiou" else "C" for c in word]
    cnt = 0

    while word:
        if ''.join(word[:2]) in ('CV', 'VC'):
            word.pop(0)
        word.pop(0)
        cnt += 1
          
    return cnt
      
      
for word in ('queue', 'piece', 'lampshade'):
    print(word, units(word))

Означает ли c в if c in "aeiou", что он проходит через word и заменяет каждую букву на V, если она находится где-то в aeiou? (Извините, если это странный/простой вопрос, ключевое слово in я использовал только один раз, и оно было намного проще, чем эта программа! Хочу убедиться, что я понимаю, как это работает)

Suntooth 26.07.2024 03:06

Также: есть ли способ адаптировать это для работы с орграфами, или это лучше подойдет для решения другого типа?

Suntooth 26.07.2024 04:02

@Suntooth — понимание списка перебирает каждую букву слова, сохраняя их как Cили V. Для орграфов вам нужна вторая система. Это обрабатывает типы символов. Диграфы представляют собой комбинации символов. Однако ваша система орграфов может позаимствовать эту систему.

OysterShucker 26.07.2024 06:29

Это можно сделать разными способами, но поскольку мне нравится стиль функционального программирования, вот одно из возможных решений:

cv = lambda s: 'v' if s in 'aeiou' else 'c'

def units(cvs):
    match tuple(cvs):
        case c, v, *cvs if cv(c) != cv(v): return c+v, *units(cvs)
        case c, v, *cvs: return c, *units((v, *cvs))
        case _: return cvs
    
units('piece')      # ('pi', 'ec', 'e')
units('queue')      # ('qu', 'e', 'u', 'e')
units('lampshade')  # ('la', 'm', 'p', 's', 'ha', 'de')

Использование регулярного выражения:

import re

def units(word) -> int:
    v = '[aeiou]'
    c = '[^aeiou]'
    return len(re.findall(f'{v}{c}?|{c}{v}?', word))

for word in 'queue', 'piece', 'lampshade':
    print(word, units(word))

Или вспоминая, какой вид мы получаем бесплатно:

def units(word) -> int:
    count = 0
    free = None
    for char in word:
        kind = char in 'aeiou'
        if kind is free:
            free = None
        else:
            count += 1
            free = not kind
    return count

for word in 'queue', 'piece', 'lampshade':
    print(word, units(word))

Попробуйте это онлайн!

Другие вопросы по теме