Declaratieve Talen/Oplossing winkelen: verschil tussen versies

Uit Wina Examenwiki
Naar navigatie springen Naar zoeken springen
Beau (overleg | bijdragen)
oplossing prolog winkelen
 
Geen bewerkingssamenvatting
Regel 1: Regel 1:
een mogelijke oplossing voor de basisopgave
=== een mogelijke oplossing voor de basisopgave ===


  prijs(delhaize, zeep, 8).
  prijs(delhaize, zeep, 8).
Regel 91: Regel 91:
  X = L;
  X = L;
  select(Lijst,X).
  select(Lijst,X).
=== Alternatieve oplossing ===
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).

Versie van 9 jan 2009 15:01

een mogelijke oplossing voor de 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).

Alternatieve oplossing

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