From 03f35fd75fb4552a1c2f0426d546ea2dcea364eb Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 21 Jan 2025 14:38:18 +0100 Subject: [PATCH] Add `food-chain` exercise (#785) (#782) --- config.json | 12 ++++ .../practice/knapsack/.docs/instructions.md | 25 ++++++++ .../practice/knapsack/.docs/introduction.md | 10 +++ exercises/practice/knapsack/.meta/config.json | 19 ++++++ exercises/practice/knapsack/.meta/example.clj | 12 ++++ .../practice/knapsack/.meta/generator.clj | 11 ++++ .../practice/knapsack/.meta/generator.tpl | 10 +++ exercises/practice/knapsack/.meta/tests.toml | 36 +++++++++++ exercises/practice/knapsack/deps.edn | 6 ++ exercises/practice/knapsack/project.clj | 4 ++ exercises/practice/knapsack/src/knapsack.clj | 7 +++ .../practice/knapsack/test/knapsack_test.clj | 63 +++++++++++++++++++ 12 files changed, 215 insertions(+) create mode 100644 exercises/practice/knapsack/.docs/instructions.md create mode 100644 exercises/practice/knapsack/.docs/introduction.md create mode 100644 exercises/practice/knapsack/.meta/config.json create mode 100644 exercises/practice/knapsack/.meta/example.clj create mode 100644 exercises/practice/knapsack/.meta/generator.clj create mode 100644 exercises/practice/knapsack/.meta/generator.tpl create mode 100644 exercises/practice/knapsack/.meta/tests.toml create mode 100644 exercises/practice/knapsack/deps.edn create mode 100644 exercises/practice/knapsack/project.clj create mode 100644 exercises/practice/knapsack/src/knapsack.clj create mode 100644 exercises/practice/knapsack/test/knapsack_test.clj diff --git a/config.json b/config.json index 86e782de4..6e4f43649 100644 --- a/config.json +++ b/config.json @@ -1290,6 +1290,18 @@ "transforming" ] }, + { + "slug": "knapsack", + "name": "Knapsack", + "uuid": "f1827715-0e86-42f2-b07d-4d70e8c2e043", + "practices": [], + "prerequisites": [ + "numbers", + "vectors", + "conditionals" + ], + "difficulty": 5 + }, { "slug": "luhn", "name": "Luhn", diff --git a/exercises/practice/knapsack/.docs/instructions.md b/exercises/practice/knapsack/.docs/instructions.md new file mode 100644 index 000000000..0ebf7914c --- /dev/null +++ b/exercises/practice/knapsack/.docs/instructions.md @@ -0,0 +1,25 @@ +# Instructions + +Your task is to determine which items to take so that the total value of her selection is maximized, taking into account the knapsack's carrying capacity. + +Items will be represented as a list of items. +Each item will have a weight and value. +All values given will be strictly positive. +Lhakpa can take only one of each item. + +For example: + +```text +Items: [ + { "weight": 5, "value": 10 }, + { "weight": 4, "value": 40 }, + { "weight": 6, "value": 30 }, + { "weight": 4, "value": 50 } +] + +Knapsack Maximum Weight: 10 +``` + +For the above, the first item has weight 5 and value 10, the second item has weight 4 and value 40, and so on. +In this example, Lhakpa should take the second and fourth item to maximize her value, which, in this case, is 90. +She cannot get more than 90 as her knapsack has a weight limit of 10. diff --git a/exercises/practice/knapsack/.docs/introduction.md b/exercises/practice/knapsack/.docs/introduction.md new file mode 100644 index 000000000..9ac9df596 --- /dev/null +++ b/exercises/practice/knapsack/.docs/introduction.md @@ -0,0 +1,10 @@ +# Introduction + +Lhakpa is a [Sherpa][sherpa] mountain guide and porter. +After months of careful planning, the expedition Lhakpa works for is about to leave. +She will be paid the value she carried to the base camp. + +In front of her are many items, each with a value and weight. +Lhakpa would gladly take all of the items, but her knapsack can only hold so much weight. + +[sherpa]: https://en.wikipedia.org/wiki/Sherpa_people#Mountaineering diff --git a/exercises/practice/knapsack/.meta/config.json b/exercises/practice/knapsack/.meta/config.json new file mode 100644 index 000000000..a72d186cc --- /dev/null +++ b/exercises/practice/knapsack/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "erikschierboom" + ], + "files": { + "solution": [ + "src/knapsack.clj" + ], + "test": [ + "test/knapsack_test.clj" + ], + "example": [ + ".meta/example.clj" + ] + }, + "blurb": "Given a knapsack that can only carry a certain weight, determine which items to put in the knapsack in order to maximize their combined value.", + "source": "Wikipedia", + "source_url": "https://en.wikipedia.org/wiki/Knapsack_problem" +} diff --git a/exercises/practice/knapsack/.meta/example.clj b/exercises/practice/knapsack/.meta/example.clj new file mode 100644 index 000000000..02601f7be --- /dev/null +++ b/exercises/practice/knapsack/.meta/example.clj @@ -0,0 +1,12 @@ +(ns knapsack) + +(defn maximum-value [maximum-weight items] + (if (empty? items) + 0 + (max + (if (<= (:weight (first items)) maximum-weight) + (+ + (:value (first items)) + (maximum-value (- maximum-weight (:weight (first items))) (rest items))) + 0) + (maximum-value maximum-weight (rest items))))) diff --git a/exercises/practice/knapsack/.meta/generator.clj b/exercises/practice/knapsack/.meta/generator.clj new file mode 100644 index 000000000..3fc64b61b --- /dev/null +++ b/exercises/practice/knapsack/.meta/generator.clj @@ -0,0 +1,11 @@ +(ns knapsack-generator + (:require [hbs.helper :refer [safe-str]])) + +(defn- update-item [item] + (safe-str (str item))) + +(defn- update-items [items] + (map update-item items)) + +(defn update-test-case [test-case] + (update-in test-case [:input :items] update-items)) diff --git a/exercises/practice/knapsack/.meta/generator.tpl b/exercises/practice/knapsack/.meta/generator.tpl new file mode 100644 index 000000000..cb9a57b12 --- /dev/null +++ b/exercises/practice/knapsack/.meta/generator.tpl @@ -0,0 +1,10 @@ +(ns knapsack-test + (:require [clojure.test :refer [deftest testing is]] + knapsack)) + +{{#test_cases.maximumValue}} +(deftest maximum-value_test_{{idx}} + (testing {{description}} + (is (= {{expected}} (knapsack/maximum-value {{input.maximumWeight}} [{{#input.items}} + {{.}}{{/input.items}}]))))) +{{/test_cases.maximumValue}} diff --git a/exercises/practice/knapsack/.meta/tests.toml b/exercises/practice/knapsack/.meta/tests.toml new file mode 100644 index 000000000..8e013ef19 --- /dev/null +++ b/exercises/practice/knapsack/.meta/tests.toml @@ -0,0 +1,36 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[a4d7d2f0-ad8a-460c-86f3-88ba709d41a7] +description = "no items" +include = false + +[3993a824-c20e-493d-b3c9-ee8a7753ee59] +description = "no items" +reimplements = "a4d7d2f0-ad8a-460c-86f3-88ba709d41a7" + +[1d39e98c-6249-4a8b-912f-87cb12e506b0] +description = "one item, too heavy" + +[833ea310-6323-44f2-9d27-a278740ffbd8] +description = "five items (cannot be greedy by weight)" + +[277cdc52-f835-4c7d-872b-bff17bab2456] +description = "five items (cannot be greedy by value)" + +[81d8e679-442b-4f7a-8a59-7278083916c9] +description = "example knapsack" + +[f23a2449-d67c-4c26-bf3e-cde020f27ecc] +description = "8 items" + +[7c682ae9-c385-4241-a197-d2fa02c81a11] +description = "15 items" diff --git a/exercises/practice/knapsack/deps.edn b/exercises/practice/knapsack/deps.edn new file mode 100644 index 000000000..561c3e2da --- /dev/null +++ b/exercises/practice/knapsack/deps.edn @@ -0,0 +1,6 @@ +{:aliases {:test {:extra-paths ["test"] + :extra-deps {io.github.cognitect-labs/test-runner + {:git/url "https://github.com/cognitect-labs/test-runner.git" + :sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}} + :main-opts ["-m" "cognitect.test-runner"] + :exec-fn cognitect.test-runner.api/test}}} \ No newline at end of file diff --git a/exercises/practice/knapsack/project.clj b/exercises/practice/knapsack/project.clj new file mode 100644 index 000000000..c7f1e1dc8 --- /dev/null +++ b/exercises/practice/knapsack/project.clj @@ -0,0 +1,4 @@ +(defproject knapsack "0.1.0-SNAPSHOT" + :description "knapsack exercise." + :url "https://github.com/exercism/clojure/tree/main/exercises/practice/knapsack" + :dependencies [[org.clojure/clojure "1.11.1"]]) diff --git a/exercises/practice/knapsack/src/knapsack.clj b/exercises/practice/knapsack/src/knapsack.clj new file mode 100644 index 000000000..1ad76d806 --- /dev/null +++ b/exercises/practice/knapsack/src/knapsack.clj @@ -0,0 +1,7 @@ +(ns knapsack) + +(defn maximum-value + "Calculates the maximum value that can be packed." + [maximum-weight items] + ;; function body + ) diff --git a/exercises/practice/knapsack/test/knapsack_test.clj b/exercises/practice/knapsack/test/knapsack_test.clj new file mode 100644 index 000000000..da6700f9e --- /dev/null +++ b/exercises/practice/knapsack/test/knapsack_test.clj @@ -0,0 +1,63 @@ +(ns knapsack-test + (:require [clojure.test :refer [deftest testing is]] + knapsack)) + +(deftest maximum-value_test_1 + (testing "no items" + (is (= 0 (knapsack/maximum-value 100 []))))) + +(deftest maximum-value_test_2 + (testing "one item, too heavy" + (is (= 0 (knapsack/maximum-value 10 [{:weight 100, :value 1}]))))) + +(deftest maximum-value_test_3 + (testing "five items (cannot be greedy by weight)" + (is (= 21 (knapsack/maximum-value 10 [{:weight 2, :value 5} + {:weight 2, :value 5} + {:weight 2, :value 5} + {:weight 2, :value 5} + {:weight 10, :value 21}]))))) + +(deftest maximum-value_test_4 + (testing "five items (cannot be greedy by value)" + (is (= 80 (knapsack/maximum-value 10 [{:weight 2, :value 20} + {:weight 2, :value 20} + {:weight 2, :value 20} + {:weight 2, :value 20} + {:weight 10, :value 50}]))))) + +(deftest maximum-value_test_5 + (testing "example knapsack" + (is (= 90 (knapsack/maximum-value 10 [{:weight 5, :value 10} + {:weight 4, :value 40} + {:weight 6, :value 30} + {:weight 4, :value 50}]))))) + +(deftest maximum-value_test_6 + (testing "8 items" + (is (= 900 (knapsack/maximum-value 104 [{:weight 25, :value 350} + {:weight 35, :value 400} + {:weight 45, :value 450} + {:weight 5, :value 20} + {:weight 25, :value 70} + {:weight 3, :value 8} + {:weight 2, :value 5} + {:weight 2, :value 5}]))))) + +(deftest maximum-value_test_7 + (testing "15 items" + (is (= 1458 (knapsack/maximum-value 750 [{:weight 70, :value 135} + {:weight 73, :value 139} + {:weight 77, :value 149} + {:weight 80, :value 150} + {:weight 82, :value 156} + {:weight 87, :value 163} + {:weight 90, :value 173} + {:weight 94, :value 184} + {:weight 98, :value 192} + {:weight 106, :value 201} + {:weight 110, :value 210} + {:weight 113, :value 214} + {:weight 115, :value 221} + {:weight 118, :value 229} + {:weight 120, :value 240}])))))