summaryrefslogtreecommitdiffstats
path: root/AufgabeFFP4.hs
blob: 758bee4519ab2f9f441039e9ab0919dd56d8cbc2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
module AufgabeFFP4
where

type Weight    = Int             -- Gewicht
type Value     = Int             -- Wert
type MaxWeight = Weight          -- Hoechstzulaessiges Rucksackgewicht
type Object    = (Weight, Value) -- Gegenstand als Gewichts-/Wertpaar
type Objects   = [Object]        -- Menge der anfaenglich gegebenen Gegenstaende
type SolKnp    = [Object]        -- Auswahl aus der Menge der anfaenglich
                                 -- gegebenen Gegenstaende; moegliche
                                 -- Rucksackbeladung, falls zulaessig

type NodeKnp   = (Value, Weight, MaxWeight, [Object], SolKnp)

-------------------------------------------------------------------------------

filterOne :: (a -> Bool) -> [a] -> [a]
filterOne p [] = []
filterOne p (x:xs)
  | p x = xs
  | otherwise = x : filterOne p xs

succKnp :: NodeKnp -> [NodeKnp]
succKnp (v, w, limit, objects, psol) =
  map (
    \(w', v') -> (
      v + v',
      w + w',
      limit,
      filterOne (== (w', v')) objects,
      (w', v') : psol
    )
  ) objects2
  where
    objects2 = filter (\(w', v') -> (w + w') <= limit) objects

-- TODO: delete?
succKnp2 :: NodeKnp -> [(Value, Weight, MaxWeight, [Object], SolKnp)]
succKnp2 (v, w, limit, objects, psol) =
  [(v + v',
    w + w',
   limit,
   [ (w'', v'') | (w'', v'') <- objects, (w'' >= w')],
   (w', v') : psol)
  | (w', v') <- objects, w + w' <= limit ]

-------------------------------------------------------------------------------

goalKnp :: NodeKnp -> Bool
goalKnp (_, w, limit, ((w', _) : _), _) = (w + w') > limit

-------------------------------------------------------------------------------

-- see lecture slide #167 ff.
data Stack a = EmptyStk
               | Stk a (Stack a)

push :: a -> Stack a -> Stack a
push x s = Stk x s

pop :: Stack a -> Stack a
pop EmptyStk = error "pop from an empty stack"
pop (Stk _ s) = s

top :: Stack a -> a
top EmptyStk = error "top from an empty stack"
top (Stk x _) = x

emptyStack :: Stack a
emptyStack = EmptyStk

stackEmpty :: Stack a -> Bool
stackEmpty EmptyStk = True
stackEmpty _  = False

searchDfs :: (Eq node) => (node -> [node]) -> (node -> Bool) -> node -> [node]
searchDfs succ goal x = search' (push x emptyStack)
  where
    search' s
      | stackEmpty s = []
      | goal (top s) = top s : search' (pop s)
      | otherwise =
        let x = top s
        in search' (foldr push (pop s) (succ x))

-------------------------------------------------------------------------------

knapsack :: Objects -> MaxWeight -> (SolKnp, Value)
knapsack objects limit = (psol, v)
  where (v, _, _, _, psol) = maximum (searchDfs succKnp goalKnp (0, 0, limit, objects, []))

-------------------------------------------------------------------------------

--binomDyn :: (Integer, Integer) -> Integer
--binomDyn (m, n) = ...
--  where ... dynamic compB... bndsB...