Привет, сообщество разработчиков, надо довести дело до конца.  В предыдущем моем опусе был вызов показать как можно использовать язык Пролог, да и показать что бы это было забавно. Превратить это в упражнение. Попробую продолжить выпендриваться демонстрировать. Коротко напомню задачу: Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and ''.
'?' Matches any single character.
'' Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial). Доказать полноту решения не удалось. На сайте, который предоставляет задание есть 1808 тестов, которые сразу увидеть нельзя, нужно написать программу и получить как ошибку очередной тест. Хардкорно я получил от него 66 и проверил свое решение — пока все работало. Но не может быть все так просто. Зачем было делать так много тестов, хочу проверить дальше... Попробую переписать данное решение на языке понятном доступном в этой системе (они отражают популярность языков программирования современности). Итак, выбираю Питон. Мощь Пролога в процедуре поиска, корни которой в методах доказательства теорем. Проще говоря, в него встроен механизм унификации и поиска с возвратом. Это еще проще говоря сопоставление плюс поиск в глубину по дереву решений. А Питон это современный Паскаль (что-то уже три языка на букву "П")), писать на нем программы доступно и школьникам. Сейчас я перепишу решение, которое было заложено в предыдущей реализации и быстренько реализую подобный прологовому поиск с возвратом. Далее запущу его в систему тестирования, и увижу верен ли был ход(код). На входе тестируемая строка и шаблон: Вроде получилось очень похоже на реализацию Пролога: Пять вариантов решения, иначе ложь. Но как сделать поиск с возвратом?, для этого использую yield, как его там называют, неоконченные(ленивые) вычисления, замыкание, элемент функционального подхода, подскажите… Он будет возвращать что-то, из чего можно будет выудить следующее решение, но если оно не приведет к правильному ответу, то перейдем на ветку программы со следующим yield, в этом и отличие от return. Эта функция примет на вход результат первой test(), если он истинен тогда все хорошо, иначе попробует перебирать еще, так и будет поиск в глубину аналогичный поведению вывода пролога. Вот, тут уже конкретно нужен return:  Ого, вот это результат, "939 / 1808 test cases passed." и "Status: Time Limit Exceeded".
Именно этого я и ждал, декларативное решение не всегда приводит к эффективной по времени выполнения реализации. Прозрачная формулировка это не быстрая формулировка. Но, тут результат питона, опробуем открывшийся тест в реализации из первой статьи, и замерим время: Время выполнения Питоном 11.10963249206543 сек., да-а многовато. Усовершенствованный механизм тестирования для Пролога: И вот такой результат Пролога (запуская не в онлайн-редакторе, локально, на одном железе с предыдущим): Похоже я плохо пользуюсь питоном ((, надо усовершенствовать, уже не так наглядно: Вот результат: 3.921879768371582 сек. (это уже ближе к исходному). Возвращаемся к арбитру:  И еще раз.  Делаю вывод, что за временные рамки выходит суммарное прохождение тестов, потому как последние два варианта решаются очень быстро. Нужна оптимизация на порядок. Что напрашивается, точно — поиск в ширину. Не продолжать решение каждой ветки, до тех пор пока не получим ложь и возвращаться к другой ветке, а просматривать решения по уровням, спускаясь одновременно по каждому варианту и постепенно углубиться далее. Попробую сделать это питоном, а потом продемонстрирую пролог. Тут уже результат для теста 939, всего 0.01585698127746582 сек.
и..., УРА это решение принимается  Попробую показать, как реализовать поиск в ширину, в декларативной реализации. Для этого есть специальные предикаты второго порядка, которые могут собрать решения в список, например bagof, setof, findall. Хорошо подходит предикат setof т.к. он уже умеет удалять дубли (в питоне для этого пришлось узнать о множествах). Итак, сделаю предикат который получает решение одного уровня, далее собираем это другим предикатом и углубляемся, вот полное решение: Тут видно, что правило, которое ранее выполняло поиск по шаблону, как бы делало переход по грани в графе, теперь превратилось в набор фактов pattrn, которые содержат возможные переходы (связи между состояниями) — это описание графа, а не код его реализующий. И результаты выполнения с временем в сек.: И это уже успешное решение не только логически но и по времени. В предыдущей статье, я хотел увидеть интерес к теме декларативного подхода. Тема "ниасилил такой подход" сразу открылась, все же интерес проявить можно. Тут я показал, что есть проблема производительности, то что написано ясно не работает быстро. Попытки создать параллельный пролог успешностью не завершились. Может тут вопрос будущего, квантовый компьютер сможет??
Итого используем задачки, на вышеуказанном сайте, для приятного времяпровождения с умом. Ну и в следующий раз, будет попытка сразу решить эффективно еще одну из хард-задач.