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)
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
},
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 66,
"metadata": {},
"outputs": [
{
"2383"
]
},
- "execution_count": 16,
+ "execution_count": 66,
"metadata": {},
"output_type": "execute_result"
}
},
{
"cell_type": "code",
- "execution_count": 60,
+ "execution_count": 69,
"metadata": {},
"outputs": [
{
" 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": [
{
"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"
]
},
{