Слова для кадавра Python

Задание звучит так:

Напишите программу, которая определит слова, подходящие под некоторый шаблон словообразования, которым в данный момент владеет кадавр.

Обозначения в шаблоне: 1 — не гласная, 0 — гласная, ? — строго одна любая буква, * — любое количество любых букв, в том числе ни одной. Гарантируется, что * в шаблоне не более одной.

Примеры:
10?010
молоко
отруби
обрат
селёдка
буханка
головы

молоко
головы

1010*0
отруби
обрат
сельдь
хлеб
грузди

Есть нечего, значить!

Часть решения мне сразу пришла в голову:

lettersG = 'ауоыиэяюеё'
lettersN = 'бвгджзйклмнпрстфхцчшщ'
st = ''
while True:
    checkW = input()
    if checkW == '':
        break
    if len(checkW) < len(w) or len(checkW) > len(w):
        continue
    for i in range(len(w)):
        if w[i] == '1':
            if checkW[i] not in lettersN:
                break
        if w[i] == '0':
            if checkW[i] not in lettersG:
                break
        if i == len(w) - 1:
            st += ' ' + checkW
            print(checkW)
if st == '': 
    print('Есть нечего, значить!') 

Это решение даже проходит несколько тестов, но всё-таки два случая у меня не учитываются. То есть это символ '?', так как я считаю, что это бесполезно. А второй случай - если в шаблоне присутствует '*'. У меня нет никаких идей, что делать, если в шаблоне встречается звёздочка. Подскажите, пожалуйста


Ответы (2 шт):

Автор решения: GrAnd

Идея для звёздочки...
Разбить шаблон на 2 части по звёздочке. Затем левую часть шаблона сравнить с начальным куском слова такой же длины как и часть шаблона. Ну а правую часть шаблона аналогично, только с куском слова с конца.

def check_part(template, word):
    lettersG = 'ауоыиэяюеё'
    lettersN = 'бвгджзйклмнпрстфхцчшщ'
    if (len(template) != len(word)):
        return False
    for t,w in zip(template, word):
        if (t == "0" and w not in lettersG) or (t == "1" and w not in lettersN):
            return False
    return True

def check(template, word):
    if "*" in template:
        left, right = template.split("*", 1)
        return check_part(left, word[:len(left)]) and check_part(right, word[len(word)-len(right):])
    else:
        return check_part(template, word)


check("10*10", "молоко")
→ Ссылка
Автор решения: SergFSM

Переводим слова на кадавр, меняем количество звездочек так, чтобы длина слова сравнялась с длиной шаблона, сравниваем слово с шаблоном. Примерно так:

inp = ['молоко','отруби','обрат','селёдка','буханка','головы']
pat = '10?010'

res = []
table = str.maketrans('ауоыиэяюеёбвгджзйклмнпрстфхцчшщьъ','0'*10 + '1'*23)
for w in inp:
    t = w.translate(table)
    p = pat.replace('*','*'*(len(w)-len(pat)+1))
    if all(i in ['*','?',j] for i,j in zip(p,t)):
        res.append(w)
print(res or 'Есть нечего, значит!')  # ['молоко', 'головы']

и результаты для других шаблонов:

inp = ['отруби','обрат','сельдь','хлеб','грузди']

pat = '1010*0'  # Есть нечего, значит!
pat = '011*0'  # ['отруби']
pat = '11?*1'  # ['хлеб']
→ Ссылка