diff options
| author | manuel <manuel@mausz.at> | 2012-04-29 15:45:29 +0200 |
|---|---|---|
| committer | manuel <manuel@mausz.at> | 2012-04-29 15:45:29 +0200 |
| commit | 5f700ec31840863e1b51fc589d42629c0f1899a0 (patch) | |
| tree | 639929423def9241632c8b72dc28b6e34dc0e4d1 | |
| parent | d35f6ed47f2e984fe614fa76265f8dc884db0744 (diff) | |
| download | ffp-5f700ec31840863e1b51fc589d42629c0f1899a0.tar.gz ffp-5f700ec31840863e1b51fc589d42629c0f1899a0.tar.bz2 ffp-5f700ec31840863e1b51fc589d42629c0f1899a0.zip | |
complete part one of exercise 4 and adding some tests
| -rw-r--r-- | AufgabeFFP4.hs | 24 | ||||
| -rw-r--r-- | TestAufgabeFFP4.hs | 54 |
2 files changed, 66 insertions, 12 deletions
diff --git a/AufgabeFFP4.hs b/AufgabeFFP4.hs index 758bee4..8e7cbf1 100644 --- a/AufgabeFFP4.hs +++ b/AufgabeFFP4.hs | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | module AufgabeFFP4 | 1 | module AufgabeFFP4 |
| 2 | where | 2 | where |
| 3 | 3 | ||
| 4 | import List | ||
| 5 | |||
| 4 | type Weight = Int -- Gewicht | 6 | type Weight = Int -- Gewicht |
| 5 | type Value = Int -- Wert | 7 | type Value = Int -- Wert |
| 6 | type MaxWeight = Weight -- Hoechstzulaessiges Rucksackgewicht | 8 | type MaxWeight = Weight -- Hoechstzulaessiges Rucksackgewicht |
| @@ -27,26 +29,17 @@ succKnp (v, w, limit, objects, psol) = | |||
| 27 | v + v', | 29 | v + v', |
| 28 | w + w', | 30 | w + w', |
| 29 | limit, | 31 | limit, |
| 30 | filterOne (== (w', v')) objects, | 32 | filterOne (== (w', v')) objects2, |
| 31 | (w', v') : psol | 33 | (w', v') : psol |
| 32 | ) | 34 | ) |
| 33 | ) objects2 | 35 | ) objects2 |
| 34 | where | 36 | where |
| 35 | objects2 = filter (\(w', v') -> (w + w') <= limit) objects | 37 | objects2 = filter (\(w', v') -> (w + w') <= limit) objects |
| 36 | 38 | ||
| 37 | -- TODO: delete? | ||
| 38 | succKnp2 :: NodeKnp -> [(Value, Weight, MaxWeight, [Object], SolKnp)] | ||
| 39 | succKnp2 (v, w, limit, objects, psol) = | ||
| 40 | [(v + v', | ||
| 41 | w + w', | ||
| 42 | limit, | ||
| 43 | [ (w'', v'') | (w'', v'') <- objects, (w'' >= w')], | ||
| 44 | (w', v') : psol) | ||
| 45 | | (w', v') <- objects, w + w' <= limit ] | ||
| 46 | |||
| 47 | ------------------------------------------------------------------------------- | 39 | ------------------------------------------------------------------------------- |
| 48 | 40 | ||
| 49 | goalKnp :: NodeKnp -> Bool | 41 | goalKnp :: NodeKnp -> Bool |
| 42 | goalKnp (_, _, _, [], _) = True | ||
| 50 | goalKnp (_, w, limit, ((w', _) : _), _) = (w + w') > limit | 43 | goalKnp (_, w, limit, ((w', _) : _), _) = (w + w') > limit |
| 51 | 44 | ||
| 52 | ------------------------------------------------------------------------------- | 45 | ------------------------------------------------------------------------------- |
| @@ -85,9 +78,16 @@ searchDfs succ goal x = search' (push x emptyStack) | |||
| 85 | 78 | ||
| 86 | ------------------------------------------------------------------------------- | 79 | ------------------------------------------------------------------------------- |
| 87 | 80 | ||
| 81 | cmpObject :: Object -> Object -> Ordering | ||
| 82 | cmpObject (w, v) (w', v') | ||
| 83 | | w == w' = compare v v' | ||
| 84 | | otherwise = compare w w' | ||
| 85 | |||
| 86 | -- it's safe to use maximum here as it will look at the first value of each tuple only | ||
| 88 | knapsack :: Objects -> MaxWeight -> (SolKnp, Value) | 87 | knapsack :: Objects -> MaxWeight -> (SolKnp, Value) |
| 89 | knapsack objects limit = (psol, v) | 88 | knapsack objects limit = (psol, v) |
| 90 | where (v, _, _, _, psol) = maximum (searchDfs succKnp goalKnp (0, 0, limit, objects, [])) | 89 | where |
| 90 | (v, _, _, _, psol) = maximum (searchDfs succKnp goalKnp (0, 0, limit, sortBy cmpObject objects, [])) | ||
| 91 | 91 | ||
| 92 | ------------------------------------------------------------------------------- | 92 | ------------------------------------------------------------------------------- |
| 93 | 93 | ||
diff --git a/TestAufgabeFFP4.hs b/TestAufgabeFFP4.hs new file mode 100644 index 0000000..55a257c --- /dev/null +++ b/TestAufgabeFFP4.hs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | module Main where | ||
| 2 | |||
| 3 | import Test.HUnit | ||
| 4 | import Control.Monad | ||
| 5 | import AufgabeFFP4 | ||
| 6 | |||
| 7 | ------------------------------------------------------------------------------- | ||
| 8 | |||
| 9 | import Data.List | ||
| 10 | |||
| 11 | type KnapsackWantedSolution = (SolKnp,Value) | ||
| 12 | type KnapsackWantedSolutions = [KnapsackWantedSolution] | ||
| 13 | type KnapsackGotSolution = (SolKnp,Value) | ||
| 14 | |||
| 15 | |||
| 16 | knapsackOk :: KnapsackWantedSolutions -> KnapsackGotSolution -> Bool | ||
| 17 | knapsackOk wanted got = any (equalKnapsack got) wanted | ||
| 18 | where | ||
| 19 | equalKnapsack (sg,vg) (sw,vw) = vg == vw && equalKnapsackContent sg sw | ||
| 20 | equalKnapsackContent sg sw = sort sg == sort sw | ||
| 21 | |||
| 22 | |||
| 23 | assertKnapsackOneOf :: String -> KnapsackWantedSolutions -> KnapsackGotSolution -> Assertion | ||
| 24 | assertKnapsackOneOf preface expected actual = unless (knapsackOk expected actual) (assertFailure msg) | ||
| 25 | where | ||
| 26 | msg = (if null preface then "" else preface ++ "\n") ++ | ||
| 27 | "expected one of: " ++ show expected ++ "\n but got: " ++ show actual | ||
| 28 | |||
| 29 | ------------------------------------------------------------------------------- | ||
| 30 | |||
| 31 | cases1 = TestLabel "knapsack" $ TestList [ | ||
| 32 | TestCase $ assertKnapsackOneOf "exercise example" | ||
| 33 | [([(2,3), (2,3), (3,4), (3,4)], 14)] | ||
| 34 | (knapsack [(2,3), (2,3), (3,4), (3,4), (5,6)] 10), | ||
| 35 | TestCase $ assertKnapsackOneOf "no objects" | ||
| 36 | [([], 0)] | ||
| 37 | (knapsack [(2,3), (2,3), (3,4), (3,4), (5,6)] 1), | ||
| 38 | TestCase $ assertKnapsackOneOf "all objects" | ||
| 39 | [([(2,3), (2,3), (3,4), (3,4), (5,6)], 20)] | ||
| 40 | (knapsack [(2,3), (2,3), (3,4), (3,4), (5,6)] 100), | ||
| 41 | TestCase $ assertKnapsackOneOf "a" | ||
| 42 | [([(2,2), (3,3)], 5), ([(5,5)], 5)] | ||
| 43 | (knapsack [(2,2), (3,3), (4,4), (5,5)] 5) | ||
| 44 | ] | ||
| 45 | |||
| 46 | cases2 = TestLabel "binomDyn" $ TestList [ | ||
| 47 | ] | ||
| 48 | |||
| 49 | tests :: [Test] | ||
| 50 | tests = [cases1, cases2] | ||
| 51 | |||
| 52 | main = do | ||
| 53 | forM tests $ \test -> | ||
| 54 | runTestTT test | ||
