Добрый вечер. Решаю задачу
тутВернуть True если слово возможно составить из слов списка-словаря, False - если нет. Одно и то же слово из словаря может быть использовано много раз, а ещё такое слово может быть подстрокой другого слова
За два дня я разработал решение способное случайно проскочить комплект тестов, но примерно в одном случае из ста оно может дать ложноположительный результат. Идея такая, преобразовать строки словаря-списка так, чтобы ни одна из них не начиналась ни с одной другой из них, а потом уже "раздевать" слово используя этот новый список. Но строки в новом списке получаются более короткими и из них возможно составить слово которое невозможно составить из строк оригинального списка
Вот код:
def new_seq(seq):
new = seq[:]
for el in seq:
for i in range(len(new)):
while new[i] != el and new[i].startswith(el):
new[i] = new[i].replace(el, '', 1)
while '' in new:
new.remove('')
if new != seq:
return new_seq(new)
return new
def new_word(word, seq):
new = word
for w in seq:
while new.startswith(w):
new = new.replace(w, '', 1)
if new != word:
return new_word(new, seq)
return new
def valid_word(seq, word):
seq = list(set(seq))
seq = new_seq(seq)
print(seq)
word = new_word(word, seq)
return not word
seq = ['cy', 'fczdqcy', 'hzjkfczd', 'hfc', 'h', 'hh', 'fczdqfczd', 'cyh', 'cyhzjk', 'mfcz', 'fczdq', 'cyfcz',
'fczdqcy', 'cycy']
word = 'cyhhhfczdqcyhzjkfczdqfczdqcycyfczdqcymfczdq'
print(valid_word(seq, word)) # False
Проблема кажется мне неустранимой. Поэтому я ищу другие подходы. Например думаю над таким: программа должна искать способ построить слово из имеющихся слогов, но если она заходит в тупик, то возвращаться обратно. Для этой цели я даже придумал оригинальный тест (первая версия программы его кстати успешно проходит):
seq = ['abcd', 'abcdd', 'abcdddd', 'ddddefg', 'defg', 'ddfgh', 'ddfghh', 'ddfghhhh', 'hhhhijk', 'hhijk', 'hijk']
word = 'abcddddefghhhhijk'
print(valid_word(seq, word)) # True
Тут слово возможно составить только из трёх слогов: 'abcdd', 'ddfghh', 'hhijk'
Третий уже очевиден если найдены первые два. А вот с первыми двумя всё не так просто. Простая "правильная" сортировка списка слов тут не поможет, так как оба раза выбирать надо не самый короткий или самый длинный слог, а средний по длине. И возможны такие ситуации, когда в одном случае (одна первая буква слога) надо выбрать самый длинный слог (или длиннее среднего), а в другом (другая первая буква) - самый короткий (или короче среднего). Я пытался в словаре сохранять эдакое "дерево вариантов" ключ - слог, от которого избавлялось слово, значение - новое слово, когда все такие ключи закончились: ключ - двухэлементный кортеж, второй элемент - второй слог от которого избавлялось слово ранее избавленное от первого, потом уже ключи из трёхэлементных кортежей - но путь показался мне тупиковым с вычислительной точки зрения, в худшем случае факториал (от количества разных слогов) возможных вариантов получается. Или даже хуже, нельзя за раз удалить все вхождения слога в строку, так как в одном месте может потребоваться удалить именно этот слог, а в другом слог частично с первым пересекающийся
UPD Хотя словарь с деревом вариантов и иначе можно строить. Например в приведённом примере слово можно начать раздевать лстрипить с трёх разных слогов, получится три разных ключа-значения, а потом обнаружить что только одно из этих значений можно ещё тремя разными способами лстрипнуть и только один вариант правильный. Но если например слово начинается с английского алфавита, а слоги: a, ab, abc, abcd, ... и так 26 слогов с последним длиной в английский алфавит, а потом ещё какие то?