Declaratieve Talen/Oplossing winkelen: verschil tussen versies
Naar navigatie springen
Naar zoeken springen
Geen bewerkingssamenvatting |
Een derde oplossing (van de basisopgave) toegevoegd. |
||
Regel 1: | Regel 1: | ||
=== | === Oplossing 1 (basisopgave) === | ||
prijs(delhaize, zeep, 8). | prijs(delhaize, zeep, 8). | ||
Regel 92: | Regel 92: | ||
select(Lijst,X). | select(Lijst,X). | ||
=== | === Oplossing 2 (volledige opgave) === | ||
Dit werkt voor zover ik getest heb. Basisopgave (bestorder) + uitbreiding (optimalorder) | Dit werkt voor zover ik getest heb. Basisopgave (bestorder) + uitbreiding (optimalorder). | ||
optimalorder(O,Plaatsing) :- | optimalorder(O,Plaatsing) :- | ||
Regel 165: | Regel 165: | ||
prijs(Wi,Pr,_), | prijs(Wi,Pr,_), | ||
plaatsing_een(On,Wi,[Pr/Wi|Pl],PlRes). | 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. |
Versie van 15 aug 2009 13:45
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.