From 977d9c457f2977212d4f08575118985c1fe1aed7 Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Fri, 12 Oct 2018 11:27:54 +0100 Subject: [PATCH] Tweaked solution 9 a bit, to check all approaches are finding the same set of items --- src/task9/task9.hs | 23 +++++++++--- src/task9/task9.ipynb | 82 ++++++++++++++++++++++++++++++++++++++----- 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/src/task9/task9.hs b/src/task9/task9.hs index dac19e1..8a999df 100644 --- a/src/task9/task9.hs +++ b/src/task9/task9.hs @@ -28,17 +28,22 @@ main = do bagsT <- TIO.readFile "data/09-bags.txt" let bags = successfulParse bagsT let limit = 5000 - -- print bags print $ part1 limit bags - print $ part2 limit bags + let dpTable = buildTable limit bags + print $ part2 dpTable limit bags + print $ backtrace dpTable ((length bags), limit) part1 :: Weight -> [Bag] -> Int part1 limit bags = length $ last $ takeWhile (willFit limit) $ inits sortedBags where sortedBags = sortBy (compare `on` bagWeight) bags willFit limit' bags' = (sum $ map bagWeight bags') < limit' -part2 :: Weight -> [Bag] -> Value -part2 limit bags = value $ table!(length bags, limit) +part2 :: DPTable -> Weight -> [Bag] -> Value +part2 table limit bags = value $ table!(length bags, limit) + + +buildTable :: Weight -> [Bag] -> DPTable +buildTable limit bags = table where initialTable = M.fromList [((0, w), TableEntry {value = 0, backpointer = (0, w)}) | w <- [0..limit]] table = foldl' includeBag initialTable [ (thisBag, bagNumber, allowedWeight) @@ -63,6 +68,16 @@ includeBag table (bag, bagNumber, weight) = withBag = TableEntry {value = value withBagEntry + bagValue bag, backpointer = withBagKey} +backtrace :: DPTable -> (Int, Weight) -> [Bag] +backtrace table key@(numberBags, weight) + | numberBags == 0 = [Bag { bagValue = 0, bagWeight = weight }] + | weight == nextWeight = backtrace table nextKey + | otherwise = (backtrace table nextKey) ++ [includedBag] + where nextKey = backpointer (table!key) + (_, nextWeight) = nextKey + includedBag = Bag { bagWeight = weight - nextWeight + , bagValue = (value (table!key)) - value (table!nextKey)} + -- Parse the input file type Parser = Parsec Void Text diff --git a/src/task9/task9.ipynb b/src/task9/task9.ipynb index 556ce5e..1852bdd 100644 --- a/src/task9/task9.ipynb +++ b/src/task9/task9.ipynb @@ -409,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 66, "metadata": {}, "outputs": [ { @@ -418,7 +418,7 @@ "2383" ] }, - "execution_count": 16, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -484,7 +484,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 69, "metadata": {}, "outputs": [ { @@ -506,18 +506,19 @@ " Element(weight=434, value=195)})" ] }, - "execution_count": 60, + "execution_count": 69, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "recursive_value(hashable_elements, weight_limit)" + "recursive_items = recursive_value(hashable_elements, weight_limit)\n", + "recursive_items" ] }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 70, "metadata": {}, "outputs": [ { @@ -526,13 +527,78 @@ "2383" ] }, - "execution_count": 61, + "execution_count": 70, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "sum(e.value for e in recursive_value(hashable_elements, weight_limit))" + "sum(e.value for e in recursive_items)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's check that these two solutions include the same elements. Use the `backtrace` function to find when new items were added to the optimal order." + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[Element(weight=301, value=134),\n", + " Element(weight=314, value=166),\n", + " Element(weight=320, value=154),\n", + " Element(weight=336, value=190),\n", + " Element(weight=337, value=140),\n", + " Element(weight=340, value=172),\n", + " Element(weight=353, value=191),\n", + " Element(weight=356, value=153),\n", + " Element(weight=359, value=171),\n", + " Element(weight=365, value=177),\n", + " Element(weight=381, value=166),\n", + " Element(weight=382, value=185),\n", + " Element(weight=414, value=189),\n", + " Element(weight=434, value=195)]" + ] + }, + "execution_count": 78, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dp_items = [element for (pre, post), element in zip(backtrace(vbr).items(), reversed(elements))\n", + " if pre[1] != post[1] ]\n", + "dp_items_fs = frozenset(\n", + " Element(weight=e['weight'], value=e['value']) for e in dp_items\n", + " )\n", + "sorted(dp_items_fs)" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "True" + ] + }, + "execution_count": 79, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dp_items_fs == recursive_items" ] }, { -- 2.34.1