2014-11-04 46 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).