RosettaCodeData/Task/Knapsack-problem-Unbounded/Haskell/knapsack-problem-unbounded.hs

39 lines
1.2 KiB
Haskell

import Data.List (maximumBy)
import Data.Ord (comparing)
(maxWgt, maxVol) = (25, 0.25)
items =
[Bounty "panacea" 3000 0.3 0.025,
Bounty "ichor" 1800 0.2 0.015,
Bounty "gold" 2500 2.0 0.002]
data Bounty = Bounty
{itemName :: String,
itemVal :: Int,
itemWgt, itemVol :: Double}
names = map itemName items
vals = map itemVal items
wgts = map itemWgt items
vols = map itemVol items
dotProduct :: (Num a, Integral b) => [a] -> [b] -> a
dotProduct factors = sum . zipWith (*) factors . map fromIntegral
options :: [[Int]]
options = filter fits $ mapM f items
where f (Bounty _ _ w v) = [0 .. m]
where m = floor $ min (maxWgt / w) (maxVol / v)
fits opt = dotProduct wgts opt <= maxWgt &&
dotProduct vols opt <= maxVol
showOpt :: [Int] -> String
showOpt opt = concat (zipWith showItem names opt) ++
"total weight: " ++ show (dotProduct wgts opt) ++
"\ntotal volume: " ++ show (dotProduct vols opt) ++
"\ntotal value: " ++ show (dotProduct vals opt) ++ "\n"
where showItem name num = name ++ ": " ++ show num ++ "\n"
main = putStr $ showOpt $ best options
where best = maximumBy $ comparing $ dotProduct vals