Бремя решения задачи переложено теперь на отношение
сумма1
. Но это отношение является уже достаточно общим, чтобы можно было определить его рекурсивно. Без ограничения общности мы предположим, что все три списка, представляющие три числа, имеют одинаковую длину. Наш пример, конечно, удовлетворяет этому условию, но если это не так, то всегда можно приписать слева нужное количество нулей к более "короткому" числу.
Определение отношения
сумма1
можно разбить на два случая:
(1) Все три числа представляются пустыми списками. Тогда
сумма1( [], [], [], 0, 0, Циф, Циф).
(2) Все три числа имеют какую-то самую левую цифру и справа от нее - остальные цифры. То есть, они имеют вид:
[D1 | N1], [D2 | N2], [D | N]
В этом случае должны выполняться два условия:
(а) Оставшиеся цифры, рассматриваемые как три числа N1, N2 и N, сами должны удовлетворять отношению
сумма1
, выдавая влево некоторый перенос C2 и оставляя некоторое подмножество неиспользованных цифр
Циф2
.
(b) Крайние левые цифры D1, D2 и D, а также перенос C2 должны удовлетворять отношению, показанному на рис. 7.1: C2, D1 и D2 складываются, давая в результате D и перенос влево. Это условие в нашей программе формулируется в виде отношения
. В его определении есть одна тонкая деталь, касающаяся применения металогического предиката
nonvar
. D1, D2 и D должны быть десятичными цифрами. Если хоть одна из этих переменных еще не конкретизирована, ее нужно конкретизировать какой-нибудь цифрой из списка
Циф2
. Как только такая конкретизация произошла, эту цифру нужно удалить из множества доступных цифр. Если D1, D2 и D уже конкретизированы, тогда, конечно, ни одна из
доступных цифр "потрачена" не будет. В программе эти действия реализуются при помощи недетерминированного вычеркивания элемента списка. Если этот элемент - не переменная, ничего не вычеркивается (конкретизации не было). Вот эта программа:
удалить( Элемент, Список, Список) :-
nonvar( Элемент), !.
удалить( Элемент, [Элемент | Список ], Список).
удалить(Элемент, [А | Список], [А | Список1]) :-
удалить( Элемент, Список, Список1).
Полная программа для решения арифметических ребусов приводится на рис. 7.2. В программу включены также определения двух ребусов. Вопрос к пролог-системе для ребуса про DONALD'a, GERALD'a и ROBERT'a с использованием этой программы выглядит так:
Иногда этот ребус упрощают, сообщая часть решения в виде дополнительного ограничения, например D равно 5. В такой форме ребус можно передать пролог-системе при помощи