Я нахожу твой набор и танец немного запутанным.Моя реализация использует некоторые функции SWI из library(lists)
, но она будет загружаться автоматически.
Мы всегда должны начинать с базового случая:
to_buy([], [], 0, 0).
Это говорит, что мы ничего не покупаем,предложений нет, цена и качество нулевые.Теперь рекурсивный случай:
to_buy(Goods, [Package|OtherPackages], TotalPrice, TotalQuality) :-
%% choose a package
package(Package, Price, Quality),
%% this package is a subset of the goods we need
subset(Package, Goods),
%% after buying this package, we will still need RemainingGoods
subtract(Goods, Package, RemainingGoods),
%% recur on the remaining goods
to_buy(RemainingGoods, OtherPackages, Subtotal, SubtotalQuality),
TotalPrice is Subtotal + Price,
TotalQuality is SubtotalQuality + Quality.
Итак, большая идея здесь также заключается в том, чтобы использовать subtract/3
, чтобы дать нам заданную разницу.Поскольку мы знаем, что Package является подмножеством товаров, мы не покупаем ничего, что нам не нужно (то есть предложение за [1,2,5]
не будет выбрано, если мы попытаемся купить [1,2,3,4]
, поскольку [1,2,5]
не являетсяподмножество [1,2,3,4]
).Затем мы можем просто повторить разность наборов и затем вести бухгалтерский учет того, что возвращается из рекурсивного вызова.
Я проверил с этой базой данных:
package([2,4], 7, 5).
package([1,3], 3, 8).
и этот запрос:
?- to_buy([1,2,3,4], Offers, Price, Quality).
Offers = [[2, 4], [1, 3]],
Price = 10,
Quality = 13 ;
Offers = [[1, 3], [2, 4]],
Price = 10,
Quality = 13 ;
false.