Пролог умножить все элементы списка
Я хочу определить предикат в Prolog, prod_list/2, который умножает каждый элемент списка. У меня проблема с пустым списком, желаю, чтобы продукт был нулевым, вместо этого я получаю false. Мой код
prod_list([H], H).
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
Я получаю результаты prod_list([4,3],Product). -> Product = 12, но когда я делаю prod_list([], Product). Я получаю false вместо Product = 0.
Пожалуйста помоги.
2 ответа
Ваша проблема в том, что ни одно предложение не соответствует пустому списку. На самом деле у вас есть рекурсивное предложение:
prod_list([H|T], Product) :- prod_list(T, Rest),
Product is H * Rest.
но его рекурсия заканчивается, когда в списке есть только элемент:
prod_list([H], H).
Итак, ни в коем случае не пустой список []
соответствует предложению, и по этой причине ответ false
(нет совпадений).
Чтобы решить вашу проблему, вам нужно включить явное предложение для пустого списка:
prod_list([],0).
prod_list([H],H).
prod_list([H|T], Product) :- prod_list(T, Rest), Product is H * Rest.
Можно найти другое решение, учитывая, что произведение пустого списка должно быть (правильно) определено следующим образом:
product_of_list([], 1).
product_of_list([H|T], Product) :- product_of_list(T, Rest), Product is H * Rest
тогда вы можете добавить свое "специальное" определение prod_list
:
prod_list([],0).
prod_list(List, Product) :- product_of_list(List, Product).
редактировать
Последнее решение не работает для некоторых интерактивных версий Prolog (например, Swish on-line), в то время как оно работает для SWI-Prolog (многопоточный, 64-битный, версия 7.3.11). Решения, которые должны работать для каждой версии, следующие:
prod_list([],0).
prod_list([H|T], Product) :- product_of_list([H|T], Product).
Спасибо user474491 за обнаружение этого.
Ответ Ренцо идеален. Я просто подумал о функциональной обработке списков, когда увидел твой вопрос. Вы можете получить их на тот случай, если они вам понадобятся. Если вы определите умножение функции:
mul(V1,V2,R) :- R is V1*V2;
тогда вы можете использовать foldl в любом из его вариантов:
?- foldl(mul, [1,2,10], 1, R).
R = 20 .
fold
является традиционной функциональной функцией вычисления, которая применяет функцию, накапливающую временный результат.