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

Popular posts from this blog

Delphi change the assembly code of a running process -

json - Hibernate and Jackson (java.lang.IllegalStateException: Cannot call sendError() after the response has been committed) -

C++ 11 "class" keyword -