Некоторое время назад я создал проблему для Codeforces April Fools Day Contest 2014 - «Feed the Golorp»: http://codeforces.com/contest/409/problem/I. Пожалуйста, прочитайте заявление о проблеме по предоставленной ссылке.Решение головоломки «Подача голограммы» в Прологе
Проблема должна была быть решена людьми, которые вообще не знают Prolog. Только 3 человека смогли решить проблему во время конкурса - в Java, Python и C++.
Основная задача - понять, что нужно сделать. Для человека с некоторым опытом Prolog должно быть почти очевидно , что имя golorp как ?(_-_/___*__):-___>__.
определяет предикат Prolog, и задача состоит в том, чтобы найти минимальные значения переменных, которые удовлетворяют предикатам. Есть несколько деталей: еще раз, пожалуйста, прочитайте заявление о проблеме.
Фактически решение проблемы после понимания цели не так уж и тривиально. Алгоритмически задача состоит в топологическом сортировании переменных по ограничениям. Название Golorp может содержать до 1024 символов, поэтому требуется эффективный алгоритм.
Я написал свое справочное решение в Python с регулярными выражениями. Но после конкурса я начал задаваться вопросом, как решить проблему в Prolog.
Из-за возможной длины имени golorp до 1024 символов, используя только обратное отслеживание Prolog для принудительной работы, все возможности не выглядят выполнимыми - возможно, необходимо программирование с ограничением логики.
Если бы я мог извлечь список всех переменных и список пар переменных из неравенств, я могу его решить. Например, в ECLIPSE CLP:
:- lib(ic).
solve(Vars, Ineqs, Result) :-
Vars :: 0..9,
(foreach((A, B), Ineqs) do
A #< B),
labeling(Vars),
concat_string(Vars, Result).
[eclipse]: Vars = [__, ___, __, ___], Ineqs = [(__, ___)], solve(Vars, Ineqs, Result).
Vars = [0, 1, 0, 1]
__ = 0
___ = 1
Ineqs = [(0, 1)]
Result = "0101"
Но я не уверен, как получить Vars = [__, ___, __, ___]
и Ineqs = [(__, ___)]
из ?(__+___+__-___):-___>__.
без слишком много кода. term_variables/2
теряет повторяющиеся переменные. DCG?
Или существует совершенно другой, лучший способ решить головоломку в Прологе? (не обязательно в ECLiPSe CLP).
Update: пару больших примеров тест:
?(_____________________*_________________________*________________________*___________________*_________________*__________________*___________________________*___*__*____________________*_________________________*_______________*____*___________*_____________*______*_____*_______________*____________*__________________*___________________________*___________________________):-_____>__,_______________<___________________,__>___________,________________________>______,_____________>______,____________________<_________________________,_________________<__________________,_____________<___,____<_________________________,______>____________,________________________>_________________________,_____<____________________,__<____________,_____________________>____________,__________________>_______________,_____>___,___________<_______________,_________________________>____,____<___________________,________________________>___________________________,____________>___________________________,_____<_______________.
Результат: 3898080517870043672800
?(___*__*_____*____*_____*___*___*_____*___*___*___*__*___*_____*___*_____*____*___*____*_____*_____*____*_____*____*____*____*___*___*__*___*____*__*_____*_____*____*____*___*__*____*___*___*____*_____*_____*____*___*__*_____*____*__*_____*___*___*___*_____*____*___*_____*_____*___*___*___*____*__*_____*_____*__*___*__*__*_____*____*_____*___*__*_____*_____*__*____*___*____*_____*_____*___*___*___*_____*__*__*__*__*___*_____*__*___*___*____*_____*___*__*_____*_____*_____*_____*_____*__*__*___*___*_____*____*___*__*___*__*___*_____*__*_____*_____*_____*____*____*___*___*_____*____*____*__*__*_____*___*__*___*_____*_____):-____>_____,___>____.
Результат: 2001022022202020121001011122021000112012210012001002220120022210000200010200001210022200000200221020000000022012020200000112201100020200
Спасибо, я многое узнал из вашего ответа. –