2014-11-04 51 views
0

我做了一个谓词,它以2个列表作为参数,并返回一个与“recipesub”产品连接的列表,但是我需要制定第三个规则来禁止如果手头的产品是空白列表,则插入产品。序言:选择不在列表递归期间插入元素

所以第一个列表看起来是这样的:

recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]). 

,第二个是这样的:

ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4), 

在它返回的那一刻:List = [ingredient(rice,1),[],ingredient(water,1)]

我希望它返回:List = [ingredient(rice,1),ingredient(water,1)]

need_to_buy([],_,List):- List = []. 
need_to_buy([H|Hs],[X|Xs],[Difference|List]):- 
    H = ingredient(Type,Amount), 
    recipesub(Type,Amount,[X|Xs],Difference), 
    need_to_buy(Hs,[X|Xs],List). 

以下是我用这个解决方案得到了多少。

/*need_to_buy([H|Hs],[X|Xs],List):- 
    H = ingredient(Type,Amount), 
    recipesub(Type,Amount,[X|Xs],Difference), 
    Difference = [], 
    need_to_buy(Hs,[X|Xs],List).*/ 

这是支持断言recipesub。

recipesub(Type,Amount,[],Difference):- 
    Difference = ingredient(Type,Amount). 
recipesub(Type,Amount,[Z|_],Difference):- 
    Z = ingredient(Type,Stock), 
    Amount>Stock, 
    NewAmount is Amount-Stock, 
    Difference = ingredient(Type,NewAmount). 
recipesub(Type,Amount,[Z|_],Difference):- 
    Z = ingredient(Type, Stock), 
    Stock >= Amount, 
    Difference = []. 
recipesub(Type,Amount,[Z|Zs],Difference):- 
    Z = ingredient(WrongType,_), 
    WrongType \= Type, 
    recipesub(Type,Amount,Zs,Difference). 
+1

[MCVE](http://stackoverflow.com/help/mcve),请。这个'recipesub/4'是什么? – false 2014-11-04 13:59:55

+0

Recipesub是一个谓词,它将第一个列表的头部与第二个列表中的每个元素进行递归比较,如果“H”中的变量“Amount”小于X中的“Amount”,则返回差值=成分(type,requiredAmount),但如果X中的变量Amount大于H中的变量Amount,则返回一个空列表。 – pinkyring 2014-11-04 14:12:08

+0

好的,对不起,我现在已经尽了我的能力。 – pinkyring 2014-11-04 14:22:50

回答

1

我通常不会做了一堆嵌套的条件,但它“感觉正确”这个时候,这是我找到了解决办法:

need_to_buy([], _, []). 
need_to_buy([ingredient(Type, AmountNeeded)|Ingredients], OnHand, Needed) :- 
    % Do we have any on-hand? 
    member(ingredient(Type, AmountOnHand), OnHand) -> 

     % If the amount on-hand is greater than the amount needed, 
     % just hand off the rest 
     (AmountOnHand >= AmountNeeded -> 
      need_to_buy(Ingredients, OnHand, Needed) 

     % otherwise, calculate the amount needed and recur 
     ; (AmountToBuy is AmountNeeded - AmountOnHand, 
      need_to_buy(Ingredients, OnHand, RestNeeded), 
      Needed = [ingredient(Type, AmountToBuy)|RestNeeded])) 

    % If we have none on-hand, we can just use the amount needed 
    % to form the request, and recur 
    ; need_to_buy(Ingredients, OnHand, RestNeeded), 
     Needed = [ingredient(Type, AmountNeeded)|RestNeeded]. 

否则我想你就会有一个很多相当低效的测试和重新测试。我在代码中看到的主要错误是您对第二个参数进行了模式匹配。依靠member/2memberchk/2可以更轻松地在现有的东西中找到正确的成分。

如果我有一堆条款做了它,而不是它可能会是这样的:

need_to_buy([], _, []). 

% case 1: we don't have the ingredient at all 
need_to_buy([ingredient(Type, AmountNeeded) | Ingredients], 
      OnHand, 
      [ingredient(Type, AmountNeeded)|Needed]) :- 
    \+ memberchk(ingredient(Type, _), OnHand), 
    need_to_buy(Ingredients, OnHand, Needed). 

% case 2: we have it, but not enough 
need_to_buy([ingredient(Type, AmountNeeded) | Ingredients], 
      OnHand, 
      [ingredient(Type, AmountToBuy)|RestNeeded]) :- 
    memberchk(ingredient(Type, AmountOnHand), OnHand), 
    AmountNeeded > AmountOnHand, 
    AmountToBuy is AmountNeeded - AmountOnHand, 
    need_to_buy(Ingredients, OnHand, RestNeeded). 

% case 3: we have enough 
need_to_buy([ingredient(Type, AmountNeeded) | Ingredients], 
      OnHand, 
      RestNeeded) :- 
    memberchk(ingredient(Type, AmountOnHand), OnHand), 
    AmountNeeded =< AmountOnHand, 
    need_to_buy(Ingredients, OnHand, RestNeeded). 

这使得在堆栈上一个选择点只是一般好像很多重新测试相同的条件和重为了我的口味而穿越。但是,如果它看起来更好,它应该工作相同。

+0

感谢您的回复,但当我看到您的代码时,我已经想出了一个解决方案。 – pinkyring 2014-11-06 20:58:11

0

我最终通过将need_to_buy的第二条规则分成两条规则来解决它,一条规则处理差异是空列表的情况以及它不是空列表的情况。

我起初遇到了一些麻烦,但事实证明规则的“方向”给了我麻烦,所以我必须将处理Difference \ = []的情况的规则放在上面,差异= []。 它现在看起来像这样:

need_to_buy([],_,List):- List = []. 
need_to_buy([H|Hs],[X|Xs],[Difference|List]):- 
    H = ingredient(Type,Amount), 
    recipesub(Type,Amount,[X|Xs],Difference), 
    Difference \= [], 
    need_to_buy(Hs,[X|Xs],List). 
need_to_buy([H|Hs],[X|Xs],List):- 
    H = ingredient(Type,Amount), 
    recipesub(Type,Amount,[X|Xs],Difference), 
    Difference = [], 
    need_to_buy(Hs,[X|Xs],List).