RosettaCodeData/Task/Knapsack-problem-Continuous/Haskell/knapsack-problem-continuous-1.hs

50 lines
1.1 KiB
Haskell
Raw Permalink Normal View History

2013-04-10 21:29:02 -07:00
import Data.List (sortBy)
import Data.Ord (comparing)
2017-09-23 10:01:46 +02:00
import Text.Printf (printf)
import Control.Monad (forM_)
2013-04-10 21:29:02 -07:00
import Data.Ratio (numerator, denominator)
2017-09-23 10:01:46 +02:00
maxWgt :: Rational
2013-04-10 21:29:02 -07:00
maxWgt = 15
data Bounty = Bounty
2017-09-23 10:01:46 +02:00
{ itemName :: String
, itemVal, itemWgt :: Rational
}
2013-04-10 21:29:02 -07:00
2017-09-23 10:01:46 +02:00
items :: [Bounty]
2013-04-10 21:29:02 -07:00
items =
2017-09-23 10:01:46 +02:00
[ Bounty "beef" 36 3.8
, Bounty "pork" 43 5.4
, Bounty "ham" 90 3.6
, Bounty "greaves" 45 2.4
, Bounty "flitch" 30 4.0
, Bounty "brawn" 56 2.5
, Bounty "welt" 67 3.7
, Bounty "salami" 95 3.0
, Bounty "sausage" 98 5.9
]
2013-04-10 21:29:02 -07:00
solution :: [(Rational, Bounty)]
solution = g maxWgt $ sortBy (flip $ comparing f) items
2017-09-23 10:01:46 +02:00
where
g room (b@(Bounty _ _ w):bs) =
if w < room
then (w, b) : g (room - w) bs
else [(room, b)]
f (Bounty _ v w) = v / w
2013-04-10 21:29:02 -07:00
2017-09-23 10:01:46 +02:00
main :: IO ()
2013-04-10 21:29:02 -07:00
main = do
2017-09-23 10:01:46 +02:00
forM_ solution $ \(w, b) -> printf "%s kg of %s\n" (mixedNum w) (itemName b)
(printf "Total value: %s\n" . mixedNum . sum) $ f <$> solution
where
f (w, Bounty _ v wtot) = v * (w / wtot)
mixedNum q =
if b == 0
then show a
else printf "%d %d/%d" a (numerator b) (denominator b)
where
a = floor q
b = q - toEnum a