Приношу извинения за, возможно, не очень полезное название; Я не мог понять, как сформулировать эту проблему в одном предложении.
Я пытаюсь подсчитать, сколько «единиц» имеет слово в 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
), но это также усложнит разработку.
Хотите ли вы найти ЛЮБОЙ результат или конкретный результат. Например, asian
должно вернуть as-i-an
или a-si-an
?
@RodrigoRodrigues - похоже, речь идет больше о поиске «единиц», и в вашем примере в любом случае это 3 единицы.
в этом случае это так же просто, как подсчитать, сколько раз вы меняете гласную на согласную или наоборот. Просто повторите один раз, никаких комбинаций не требуется.
@RodrigoRodrigues - вы не можете просто посчитать переходы, потому что «CV» и «VC» — это единица измерения. Пример: «CVVVC» в вашем подсчете равен 2, но реальный счет равен 3. Мой ответ иллюстрирует 1 способ получить правильный счет. Я мог бы сделать это более прямолинейно, но я решил упростить понимание.
Просто преобразуйте все в «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 — понимание списка перебирает каждую букву слова, сохраняя их как C
или V
. Для орграфов вам нужна вторая система. Это обрабатывает типы символов. Диграфы представляют собой комбинации символов. Однако ваша система орграфов может позаимствовать эту систему.
Это можно сделать разными способами, но поскольку мне нравится стиль функционального программирования, вот одно из возможных решений:
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))
Зачем вам перебирать каждую комбинацию? Почему бы просто не проверить, является ли одно гласным, а другое — согласным?