Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 序言:选择在列表递归期间不插入元素_List_Recursion_Prolog - Fatal编程技术网

List 序言:选择在列表递归期间不插入元素

List 序言:选择在列表递归期间不插入元素,list,recursion,prolog,List,Recursion,Prolog,我做了一个谓词,它将2个list作为参数,并返回一个与“recipesub”的乘积连接的列表,但是我需要做第三个规则,如果手头的产品是空列表,则禁止插入该产品 因此,第一个列表可以如下所示: recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]). ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4), need_to_buy

我做了一个谓词,它将2个list作为参数,并返回一个与“recipesub”的乘积连接的列表,但是我需要做第三个规则,如果手头的产品是空列表,则禁止插入该产品

因此,第一个列表可以如下所示:

recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]).
ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4),
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).
第二个是这样的:

recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]).
ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4),
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).
当它返回时:
List=[配料(大米,1),[],配料(水,1)]

我希望它返回:
List=[配料(大米,1),配料(水,1)]

下面是我在解决方案方面取得的进展

/*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).

我通常不会做很多嵌套条件,但这次“感觉不错”,这就是我找到的解决方案:

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/2
memberchk/2
可以更轻松地从手头的东西中找到合适的成分

如果我用一堆子句来代替,它可能会是这样的:

recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]).
ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4),
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).
需要购买([],[])。
%案例1:我们根本没有原料
需要购买([配料(类型、所需数量)|配料],
现在,
[成分(类型、所需数量)|所需]:-
\+memberchk(成分(类型),现有),
需要购买(原料、现货、需要)。
%案例2:我们有,但还不够
需要购买([配料(类型、所需数量)|配料],
现在,
[成分(类型、购买量)|需要时]:-
memberchk(成分(类型、数量和数量),现有),
需要的数量>需要的数量,
AmountToBuy是所需数量-AmountOnHand,
需要购买(原料、现货、需要时)。
%案例3:我们已经足够了
需要购买([配料(类型、所需数量)|配料],
现在,
(需要时):-
memberchk(成分(类型、数量和数量),现有),
AmountNeeded=

这在堆栈上留下了一个选择点,通常看起来像是为了我的口味重新测试相同的条件和遍历。但是,如果你觉得它更好的话,它也应该起同样的作用。

我最终解决了这个问题,将第二条“需要购买”规则分为两条,一条处理差异是空列表的情况,另一条处理差异不是空列表的情况

一开始我遇到了一些麻烦,但事实证明规则的“方向”给我带来了麻烦,所以我不得不将处理差异\=[]情况的规则置于差异=[]的规则之上。 现在看起来是这样的:

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).

请这是什么?
recipesub/4
?recipesub是一个谓词,它递归地将第一个列表的头与第二个列表中的每个元素进行比较,如果“H”中的变量“Amount”小于X中的“Amount”,则返回差=成分(type,requiredAmount),但如果X中的可变金额大于H中的可变金额,则返回一个空列表。好的,对不起,我现在已尽我所能进行了更正。您可以在
需要购买
谓词中检查
[]
(从
配方返回
),或者你可以让
recipesub
失败,而不是提供
[]
作为解决方案,当
recipesub
失败时,让
need\u\u购买
“做正确的事情”。谢谢你的回复,但当我看到你的代码时,我已经想出了一个解决方案。