Prolog: Choosing NOT to insert an element during list recursion -
Prolog: Choosing NOT to insert an element during list recursion -
i've made predicate takes 2 list arguments , returns list concatenated product of "recipesub", need create 3rd rule prohibits product beingness inserted if product @ hand empty list.
so first list this:
recipe([ingredient(rice,4),ingredient(salt,3),ingredient(water,5)]).
and sec 1 this:
ingredients([ingredient(rice,3),ingredient(salt,4),ingredient(water,4),
at moment returns: list = [ingredient(rice,1),[],ingredient(water,1)]
i want return: 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).
below how far i've gotten solution.
/*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).*/
and support-predicate, recipesub.
recipesub(type,amount,[],difference):- difference = ingredient(type,amount). recipesub(type,amount,[z|_],difference):- z = ingredient(type,stock), amount>stock, newamount 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).
i don't bunch of nested conditionals "felt right" time, , solution found:
need_to_buy([], _, []). need_to_buy([ingredient(type, amountneeded)|ingredients], onhand, needed) :- % have on-hand? member(ingredient(type, amountonhand), onhand) -> % if amount on-hand greater amount needed, % hand off rest (amountonhand >= amountneeded -> need_to_buy(ingredients, onhand, needed) % otherwise, calculate amount needed , recur ; (amounttobuy amountneeded - amountonhand, need_to_buy(ingredients, onhand, restneeded), needed = [ingredient(type, amounttobuy)|restneeded])) % if have none on-hand, can utilize amount needed % form request, , recur ; need_to_buy(ingredients, onhand, restneeded), needed = [ingredient(type, amountneeded)|restneeded].
otherwise think you'll have lot of inefficient testing , retesting. main error see in code you're pattern matching on sec argument. it's easier rely on member/2
or memberchk/2
dirty work of finding right ingredient in stuff have on-hand.
if did bunch of clauses instead this:
need_to_buy([], _, []). % case 1: don't have ingredient @ need_to_buy([ingredient(type, amountneeded) | ingredients], onhand, [ingredient(type, amountneeded)|needed]) :- \+ memberchk(ingredient(type, _), onhand), need_to_buy(ingredients, onhand, needed). % case 2: have it, not plenty need_to_buy([ingredient(type, amountneeded) | ingredients], onhand, [ingredient(type, amounttobuy)|restneeded]) :- memberchk(ingredient(type, amountonhand), onhand), amountneeded > amountonhand, amounttobuy amountneeded - amountonhand, need_to_buy(ingredients, onhand, restneeded). % case 3: have plenty need_to_buy([ingredient(type, amountneeded) | ingredients], onhand, restneeded) :- memberchk(ingredient(type, amountonhand), onhand), amountneeded =< amountonhand, need_to_buy(ingredients, onhand, restneeded).
this leaves selection point on stack , seems lot of retesting same conditions , re-traversal taste. if looks improve should work same.
list recursion prolog
Comments
Post a Comment