50 lines
1.1 KiB
Haskell
50 lines
1.1 KiB
Haskell
import Data.List (sortBy)
|
|
import Data.Ord (comparing)
|
|
import Text.Printf (printf)
|
|
import Control.Monad (forM_)
|
|
import Data.Ratio (numerator, denominator)
|
|
|
|
maxWgt :: Rational
|
|
maxWgt = 15
|
|
|
|
data Bounty = Bounty
|
|
{ itemName :: String
|
|
, itemVal, itemWgt :: Rational
|
|
}
|
|
|
|
items :: [Bounty]
|
|
items =
|
|
[ 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
|
|
]
|
|
|
|
solution :: [(Rational, Bounty)]
|
|
solution = g maxWgt $ sortBy (flip $ comparing f) items
|
|
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
|
|
|
|
main :: IO ()
|
|
main = do
|
|
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
|