Declaratieve Talen/Oplossing Medicijnen

Uit Wina Examenwiki
Versie door 10.92.118.11 (overleg) op 17 jan 2009 om 15:16
Naar navigatie springen Naar zoeken springen
-- Idee: Elke ronde begint met een nieuw paar van (ophaalcapaciteit, aflevercapaciteit)
-- Na elk bezoek moeten beide capaciteiten >= 0 en <= kamionetcapaciteit zijn

ronde :: Int -> [(String, Int)] -> [(String, Int)] -> [String]
ronde cap heen terug = 
	let
		joined = join heen terug
	in
		doall cap joined

doall :: Int -> [(String, (Int, Int))] -> [String]
doall _ [] = []
doall cap deliveries = 
	let
		(steden, remainingdeliveries) = ronde2 cap (0, cap) deliveries
	in
		steden ++ "depot" : doall cap remainingdeliveries

join :: [(String, Int)] -> [(String, Int)] -> [(String, (Int, Int))]
join [] [] 			= []
join [(s1, h1)] [] 	= [(s1, (h1, 0))]			-- stad waar enkel geleverd moet worden
join [] [(s2, h2)] 	= [(s2, (0, h2))]			-- stad waar enkel afgehaald moet worden
join heen@((s1, h1) : hs) terug@((s2, h2) : ts)
	| s1 == s2		= (s1, (h1, h2)): join hs ts	-- stad waar geleverd als opgehaald moet worden
	| s1 < s2		= (s1, (h1, 0))	: join hs terug	-- stad waar enkel geleverd moet worden
	| s1 > s2		= (s2, (0, h2))	: join heen ts 	-- stad waar enkel afgehaald moet worden
	
ronde2 :: Int -> (Int, Int) -> [(String, (Int, Int))] -> ([String], [(String, (Int, Int))])
ronde2 _ _ [] = ([], [])
ronde2 cap (afcap, opcap) (entry@(stad, (af, op)) : xs) =
	let
		remafcap = afcap + af
		remopcap = opcap - op
		remafcapok = remafcap <= cap && remafcap >= 0
		remopcapok = remopcap <= cap && remopcap >= 0
	in
		if remafcapok && remopcapok
		then
			let	(a, b) = ronde2 cap (remafcap, remopcap) xs
			in	(stad : a, b) 
		else
			let	(a, b) = ronde2 cap (afcap, opcap) xs
			in	(a, entry : b)