Declaratieve Talen/Oplossing Medicijnen
Naar navigatie springen
Naar zoeken springen
import Data.List -- Dit maakt de type signatures duidelijker. type Capaciteit = Integer type Apotheek = String type Levering = (Apotheek,Integer) type Ophaling = (Apotheek,Integer) type Pad = [String] -- Bereken een route waarbij elke apotheek één keer bezocht wordt -- en waarbij men zo weinig mogelijk moet terugkeren naar het depot. ronde :: Capaciteit -> [Levering] -> [Ophaling] -> Pad ronde c l o = bestePad (map reverse (ronde' [])) where ronde' h | sort h == sort (apotheken l o) = [[]] | otherwise = [ voegToe a rest | a <- apotheken l o, a `notElem` h, rest <- ronde' (a:h)] voegToe a rest = if kanErBij c a l o rest then a:rest else a:"depot":rest -- Geef een lijst met alle apotheken waar iets opgehaald/geleverd moet worden. apotheken :: [Levering] -> [Ophaling] -> [Apotheek] apotheken leveringen ophalingen = nub [a|(a,_) <- (leveringen ++ ophalingen)] -- Controleer of de koerier een volgende apotheek er nog bij kan nemen -- zonder te moeten terugkeren naar het depot. kanErBij :: Capaciteit -> Apotheek -> [Levering] -> [Ophaling] -> Pad -> Bool kanErBij c a l o p = let leveren = (leverenAantal a l) + (capaciteitVertrek l p) ophalen = (ophalenAantal a o) + (capaciteitEind o p) combo = (leverenAantal a l) + (capaciteitEind o p) in leveren <= c && ophalen <= c && combo <= c -- Bepaal hoeveel er geleverd moet worden in een apotheek. leverenAantal :: Apotheek -> [Levering] -> Integer leverenAantal a [] = 0 leverenAantal a ((b,h):ls)| a == b = h | otherwise = leverenAantal a ls -- Bepaal hoeveel er opgehaald moet worden in een apotheek. ophalenAantal :: Apotheek -> [Ophaling] -> Integer ophalenAantal a [] = 0 ophalenAantal a ((b,h):ls)| a == b = h | otherwise = ophalenAantal a ls -- Geef het deel van het pad na het laatste bezoek aan het depot. padNaDepot :: Pad -> Pad padNaDepot [] = [] padNaDepot (a:p) | "depot" `elem` (a:p) = padNaDepot p | otherwise = (a:p) -- Bereken de capaciteit die nodig is voor de leveringen. -- (Pad bevat geen depot) capaciteitVertrek :: [Levering] -> Pad -> Capaciteit capaciteitVertrek ((a,h):ls) p = capaciteitVertrek' ((a,h):ls) p 0 where capaciteitVertrek' [] p acc = acc capaciteitVertrek' ((a,h):ls) p acc | a `elem` p = capaciteitVertrek' ls p (acc + h) | otherwise = capaciteitVertrek' ls p acc -- Bereken de gebruikte capaciteit bij het ophalen. -- (Pad bevat geen depot) capaciteitEind :: [Ophaling] -> Pad -> Capaciteit capaciteitEind ((a,h):ls) p = capaciteitEind' ((a,h):ls) p 0 where capaciteitEind' [] p acc = acc capaciteitEind' ((a,h):ls) p acc | a `elem` p = capaciteitEind' ls p (acc + h) | otherwise = capaciteitEind' ls p acc -- Haal uit een lijst van paden het pad waarbij de koerier het minste -- moet terugkeren naar de depot. Indien er meerdere minimale paden zijn -- kiezen we het alfabetisch eerste pad. bestePad :: [Pad] -> Pad bestePad paden = (sort (filter (\x -> (aantalDepot x) == mini) paden)) !! 0 where mini = minimum (map aantalDepot paden) -- Tel het aantal keer dat de koerier langs het depot passeert in een pad. aantalDepot :: Pad -> Int aantalDepot p = sum $ map (\x -> if x == "depot" then 1 else 0) p
-- 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)
import List ronde::Int->[([Char],Int)]->[([Char],Int)]->[[Char]] ronde max heen terug = (minOpl (zoekOplossingen (permuteer (zetOm heen terug)) max)) zetOm::[([Char],Int)]->[([Char],Int)]->[([Char],Int,Int)] zetOm [] [] = [] zetOm [] ((a,y):ys) = [(a,0,y)] ++ (zetOm [] ys) zetOm ((a,x):xs) ys|(zoekZelfde a ys) == 0 = [(a,x,0)]++ (zetOm xs ys) |otherwise = [(a,x,(zoekZelfde a ys))] ++ (zetOm xs (delete (a,(zoekZelfde a ys)) ys)) zoekZelfde::[Char]->[([Char],Int)]->Int zoekZelfde a [] = 0 zoekZelfde a ((b,x):xs)|a==b = x |otherwise = (zoekZelfde a xs) permuteer::[([Char],Int,Int)]->[[([Char],Int,Int)]] permuteer [] = [[]] permuteer (h:t) = concatMap (permIns h) (permuteer t) permIns::([Char],Int,Int)->[([Char],Int,Int)]->[[([Char],Int,Int)]] permIns x [] = [[x]] permIns x (h:t) = (x:h:t) : map (h:) (permIns x t) zoekOplossingen::[[([Char],Int,Int)]]->Int->[([[Char]],Int)] zoekOplossingen [] _ = [] zoekOplossingen (x:xs) max = [(zoekOpl x max)] ++ (zoekOplossingen xs max) zoekOpl::[([Char],Int,Int)]->Int->([[Char]],Int) zoekOpl ((a,x,y):xs) max= ([a] ++ (zoekOpl2 x y xs max) , (hoeveelDep (zoekOpl2 x y xs max))) zoekOpl2::Int->Int->[([Char],Int,Int)]->Int->[[Char]] zoekOpl2 _ _ [] _ = ["depot"] zoekOpl2 x1 y1 ((a,x2,y2):xs) max = if (and [((x1+x2)<=max),((y1+x2)<=max),((y1+y2)<=max)]) then [a] ++ (zoekOpl2 (x1+x2) (y1+y2) xs max) else ["depot",a] ++ (zoekOpl2 x2 y2 xs max) hoeveelDep::[[Char]]->Int hoeveelDep [] = 0 hoeveelDep (x:xs)|x=="depot" = 1 + (hoeveelDep xs) |otherwise = 0 + (hoeveelDep xs) minOpl::[([[Char]],Int)]->[[Char]] minOpl ((x,aantal):xs) = (minOpl2 x aantal xs) minOpl2::[[Char]]->Int->[([[Char]],Int)]->[[Char]] minOpl2 x aantal [] = x minOpl2 x aantal ((x2,aantal2):xs)|aantal2<aantal = (minOpl2 x2 aantal2 xs) |otherwise = (minOpl2 x aantal xs)
--Lynn 17 jan 2011 15:56 (UTC)
import List import Data.Ord gewicht (loc,lev,oph) = oph - lev prioriteit:: [(String,Int,Int)] -> [(String,Int,Int)] prioriteit lijst = sortBy (comparing gewicht) lijst kanLeveren:: Int -> Int -> Int -> (String,Int,Int) -> Bool kanLeveren waren afval capaciteit (_,gevraagd,vuil) | gevraagd <= waren, afval + waren - gevraagd + vuil <= capaciteit = True | otherwise = False kanErgensLeveren:: Int -> Int -> Int -> [(String,Int,Int)] -> Bool kanErgensLeveren _ _ _ [] = False kanErgensLeveren waren afval capaciteit (x:xs) | kanLeveren waren afval capaciteit x = True | otherwise = kanErgensLeveren waren afval capaciteit xs ronde:: Int -> [(String,Int)] -> [(String,Int)] -> [String] ronde cap leveren ophalen = refill cap $ join leveren ophalen refill:: Int -> [(String,Int,Int)] -> [String] refill _ [] = ["depot"] refill cap lijst = ("depot") : (ronde' cap 0 cap (prioriteit lijst)) ronde':: Int -> Int -> Int -> [(String,Int,Int)] -> [String] ronde' _ _ cap [] = refill cap [] ronde' waren afval cap (x@(loc,telev,teoph):xs) |(kanLeveren waren afval cap x) = loc : (ronde' (waren-telev) (afval+teoph) cap xs) |(kanErgensLeveren waren afval cap (x:xs)) = ronde' waren afval cap (xs++[x]) | otherwise = refill cap (x:xs) 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
--Gebruiker:Laurent Indekeu 16 jan 2012 22:46 (UTC)
Nog eentje.
import List -- (capaciteit)->(ophaal)->(afhaal)->(route) ronde::Int->[(String,Int)]->[(String,Int)]->[String] ronde c heen terug = ronde2 c (city heen terug) ronde2::Int->[(String,(Int,Int))]->[String] ronde2 _ [] = [] ronde2 c list@(x:xs) = let delivRound = [fst x] ++ (findCompatibleCitys c x xs []) ++ ["depot"] in delivRound ++ (ronde2 c (otherCitys delivRound list)) otherCitys::[String]->[(String,(Int,Int))]->[(String,(Int,Int))] otherCitys [] list = list otherCitys (x:xs) list | lookup x list == Nothing = otherCitys xs list | otherwise = otherCitys xs (delete (x,(lookup2 x list)) list) findCompatibleCitys::Int->(String,(Int,Int))->[(String,(Int,Int))]->[(String,(Int,Int))]->[String] findCompatibleCitys _ _ [] cc = map fst cc findCompatibleCitys cap town@(t,(a,b)) (x:xs) cc = let target = (fst x,(getHeen x,getTerug x)) in if cap >= a + getHeen x + getHeenAll cc && cap >= b + getHeen x + getHeenAll cc && cap >= b + getTerug x + getHeenAll cc && cap >= b + getTerug x + getTerugAll cc then findCompatibleCitys cap town xs (target:cc) else findCompatibleCitys cap town xs cc getHeenAll::[(String,(Int,Int))]->Int getHeenAll [] = 0 getHeenAll (x:xs) = (fst (snd x)) + (getHeenAll xs) getTerugAll::[(String,(Int,Int))]->Int getTerugAll [] = 0 getTerugAll (x:xs) = (snd (snd x)) + (getTerugAll xs) getHeen::(String,(Int,Int))->Int getHeen (_,(a,_)) = a getTerug::(String,(Int,Int))->Int getTerug (_,(_,b)) = b city::[(String,Int)]->[(String,Int)]->[(String,(Int,Int))] city [] (y:ys) = (fst y,(0,snd y)):(city [] ys) city (x:xs) [] = (fst x,(snd x,0)):(city xs []) city [] [] = [] city (x:xs) (y:ys) | fst x == fst y = (fst x,(snd x,snd y)):(city xs ys) | otherwise = city (x:xs) ys allDest::[(String,Int)]->[(String,Int)]->[String] allDest heen terug = List.nub $ (map fst heen) ++ (map fst terug) lookup2::String->[(String,(Int,Int))]->(Int,Int) lookup2 _ [] = (0,0) lookup2 a (x:xs) | a == (fst x) = snd x | otherwise = lookup2 a xs
--Gebruiker:Andries 17 jan 2012