Declaratieve Talen/Oplossing winkelen
Naar navigatie springen
Naar zoeken springen
Oplossing 1 (basisopgave)
prijs(delhaize, zeep, 8). prijs(delhaize, prei, 10). prijs(delhaize, zout, 6). prijs(carrefour, prei, 9). prijs(carrefour, soep, 19). prijs(champion, zeep, 7). prijs(champion, prei, 11). prijs(champion, pinda, 6). leveranciers([delhaize,carrefour,champion]). bestorder(Bestelling, Plaatsing) :- findall(P, bestelling(Bestelling, P), Ps), list_to_set(Ps,Pset), filter_2(Pset,Max2Ps), minimum_kost(Max2Ps, Bestelling, Plaatsing). %zoek de plaatsing met de laagste kost uit een lijst van plaatsingen minimum_kost([P],_, MinP) :- MinP = P. minimum_kost([P|Ps],Bestelling, MinP) :- minimum_kost(Ps, Bestelling, MinPSub), kost(Bestelling, P, KostP), kost(Bestelling, MinPSub, SubKost), (KostP < SubKost -> MinP = P ; MinP = MinPSub ). %filter plaatsingen met meer dan 2 winkels filter_2([P],Ps) :- (max_2_winkels(P) -> Ps = [P] ; Ps = [] ). filter_2([P|Prest],Ps) :- filter_2(Prest,Precur), (max_2_winkels(P) -> Ps = [P|Precur] ; Ps = [Precur] ). %bestaat de plaatsing uit maximaal 2 winkels? max_2_winkels([_/_]). max_2_winkels([_/Winkel|Rest]) :- max_2_winkels(Rest, [Winkel]). max_2_winkels([_/Winkel],Winkels) :- list_to_set([Winkel|Winkels],X), length(X,Aantal), Aantal =< 2. max_2_winkels([_/Winkel|Rest],Winkels) :- list_to_set([Winkel|Winkels],VerschillendeWinkels), length(VerschillendeWinkels,Aantal), Aantal =< 2, max_2_winkels(Rest,[Winkel|Winkels]). %kost van een bestelling/plaatsing kost([Product/Aantal], [Product/Winkel],TotaalKost) :- prijs(Winkel, Product, StukKost), TotaalKost is StukKost * Aantal. kost([Product/Aantal|RestBest],[Product/Winkel|RestPlaatsing], TotaalKost) :- kost(RestBest,RestPlaatsing, Subkost), prijs(Winkel, Product, StukKost), Kost is StukKost * Aantal, TotaalKost is Kost + Subkost. %een mogelijke bestelling bestelling([Product/_],Plaatsing) :- leveranciers(Product, Leveranciers), select(Leveranciers, Leverancier), Plaatsing = [Product/Leverancier]. bestelling([X|Xs],Plaatsing) :- bestelling(Xs,P1), bestelling([X],[P2]), Plaatsing = [P2|P1]. %alle leveranciers van een product leveranciers(Product, Leveranciers) :- findall(X,prijs(X,Product,_),Leveranciers). %selecteer een element uit een lijst select([L],X) :- X = L. select([L|Lijst],X) :- X = L; select(Lijst,X).
Oplossing 2 (volledige opgave)
Dit werkt voor zover ik getest heb. Basisopgave (bestorder) + uitbreiding (optimalorder).
optimalorder(O,Plaatsing) :- findall(P,bestorder(O,P),Pn), findall(P-Prijs,(member(P,Pn),totale_korting(O,P,Kort),kost(O,P,Kost),Prijs is Kost-Kort),PKn), findall(K,member(_-K,PKn),Kn), min_list(Kn,Min), member(Plaatsing-Min,PKn), !. totale_korting(O,P,K) :- zoek_winkels(P,Wn), korting(O,P,Wn,0,K). zoek_winkels(P,Wn) :- findall(W,member(_/W,P),WDub), list_to_set(WDub,Wn). korting(_,_,[],K,K). korting(O,P,[W|Wn],K,TotK) :- findall(Am,(member(Pr/W,P),member(Pr/Am,O)),Ams), sumlist(Ams,Sum), kortingspercentage(W,Sum,Korting), Knew is Korting + K, korting(O,P,Wn,Knew,TotK). bestorder(O,Plaatsing) :- findall(P-K,(plaatsing(O,P),kost(O,P,K)),PKnDub), list_to_set(PKnDub,PKn), findall(K,member(_-K,PKn),Kn), min_list(Kn,Min), member(Plaatsing-Min,PKn). kost(O,Pl,Kost) :- kost(O,Pl,0,Kost). kost(_,[],K,K) :- !. kost(Order,[Pr/W|Pn],Kost,TotKost) :- prijs(W,Pr,P), member(Pr/Am,Order), K is Kost + P * Am, kost(Order,Pn,K,TotKost), !. plaatsing(O,Res) :- findall(Wi,prijs(Wi,_,_),WnDub), list_to_set(WnDub,Wn), ( plaatsing_een(O,Res,Wn) ; plaatsing_twee(O,Res,Wn) ). plaatsing_twee(Order,Plaatsing,Wn) :- select(W1,Wn,Wrest), member(W2,Wrest), plaatsing_twee(Order,W1,W2,[],Plaatsing). plaatsing_twee([],_,_,P,P). plaatsing_twee([Pr/_|On],W1,W2,Pl,PlRes) :- ( prijs(W1,Pr,_), W = W1 ; prijs(W2,Pr,_), W = W2 ), plaatsing_twee(On,W1,W2,[Pr/W|Pl],PlRes). plaatsing_een(Order,Plaatsing,Wn) :- member(W,Wn), plaatsing_een(Order,W,[],Plaatsing). plaatsing_een([],_,P,P). plaatsing_een([Pr/_|On],Wi,Pl,PlRes) :- prijs(Wi,Pr,_), plaatsing_een(On,Wi,[Pr/Wi|Pl],PlRes).
Oplossing 3 (basisopgave)
% Overzicht van alle tarieven. prijs(delhaize, zeep, 8). prijs(delhaize, prei, 10). prijs(delhaize, zout, 6). prijs(carrefour, prei, 9). prijs(carrefour, soep, 19). prijs(champion, zeep, 7). prijs(champion, prei, 11). prijs(champion, pinda, 6). % Lijst van leveranciers. leveranciers([delhaize,carrefour,champion]). % Berekent alle plaatsingen die voldoen aan de minimale totaalprijs. bestorder(Lijst, Resultaat) :- findall(Totaal-Plaatsing, (plaatsingen(Lijst, Plaatsing), maxtwee(Plaatsing), totaal(Plaatsing, Totaal)), MogelijkePlaatsingen), geef_minimum(MogelijkePlaatsingen, MinimalePlaatsing), geef_plaatsing(MinimalePlaatsing, MogelijkePlaatsingen, Resultaten), member(Resultaat, Resultaten). % Geeft de minimale totaalprijs van een lijst met mogelijke plaatsingen. geef_minimum([Totaal-_Plaatsing], Totaal) :- !. geef_minimum([Totaal-_Plaatsing|Rest], Minimum) :- geef_minimum(Rest, TussenTotaal), Minimum is min(Totaal, TussenTotaal). % Geeft alle plaatsingen die voldoen aan de minimale totaalprijs. geef_plaatsing(Minimum, Lijst, Resultaat) :- findall(Plaatsing, member(Minimum-Plaatsing, Lijst), Resultaat). % Berekent de totale prijs van een order. totaal([], 0) :- !. totaal([Product/Leverancier|Rest], Totaal) :- prijs(Leverancier, Product, Prijs), totaal(Rest, TussenTotaal), Totaal is Prijs + TussenTotaal. % Gaat na welke leverancier een bepaald deel van een plaatsing voor zijn rekening kan nemen. plaatsingen([], []) :- !. plaatsingen(Lijst, [Product/Leverancier|Rest]) :- select(Product/_Aantal, Lijst, NieuweLijst), prijs(Leverancier, Product, _Prijs), plaatsingen(NieuweLijst, Rest). % Stelt een lijst op van alle leveranciers die een deel van een plaatsing uitvoeren. geef_leveranciers([], []) :- !. geef_leveranciers([_Product/Leverancier|Rest], [Leverancier|Resultaat]) :- geef_leveranciers(Rest, Resultaat). % Gaat na of de plaatsing door maximaal twee verschillende leveranciers uitgevoerd wordt. maxtwee(Plaatsing) :- geef_leveranciers(Plaatsing, Lijst), list_to_set(Lijst, Verzameling), length(Verzameling, Aantal), Aantal =< 2.
Nog een oplossing, enkel basisopgave
%Feiten vind je wel in de andere oplossingen bestorder(Bestelling, Plaatsing):- findall(MogPlaatsing, (maakbestelling(Bestelling, MogPlaatsing), max2winkels(Bestelling)), MogelijkePlaatsingen), goedkoopste(MogelijkePlaatsingen, Bestelling, Plaatsing). maakbestelling([], []). maakbestelling([Product/_Prijs|RestBestelling], [Bestelling|NogTeBestellen]):- prijs(Winkel, Product, _), Bestelling = Product/Winkel, maakbestelling(RestBestelling, NogTeBestellen). max2winkels(Bestelling):- findall(Winkel, member(_/Winkel, Bestelling), Winkels), list_to_set(Winkels, WinkelsSet), length(WinkelsSet, AantalWinkels), AantalWinkels =< 2. goedkoopste(MogelijkePlaatsingen, Bestelling, Goedkoopste):- berekenprijzen(MogelijkePlaatsingen, Bestelling, PlaatsingEnPrijs), findall(Prijs, member(_-Prijs, PlaatsingEnPrijs), Prijzen), min_list(Prijzen, LaagstePrijs), member(Goedkoopste-LaagstePrijs, PlaatsingEnPrijs). berekenprijzen([], _Bestelling, []). berekenprijzen([Plaatsing|Rest], Bestelling, [Plaatsing-Prijs|Overige]):- prijsplaatsing(Plaatsing, Bestelling, Prijs), berekenprijzen(Rest, Bestelling, Overige). prijsplaatsing([], _Bestelling, 0). prijsplaatsing([Product/Winkel|OverigeProducten], Bestelling, Prijs):- prijsplaatsing(OverigeProducten, Bestelling, DeelPrijs), prijs(Winkel, Product, EenheidsPrijs), member(Product/Hoeveelheid, Bestelling), Prijs is DeelPrijs + (Hoeveelheid * EenheidsPrijs).
--Harm.de.weirdt 12 jan 2012 14:31 (CET)