diff --git a/config.json b/config.json
index be78a59cc..2942d5a61 100644
--- a/config.json
+++ b/config.json
@@ -2149,6 +2149,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 2
+ },
+ {
+ "slug": "knapsack",
+ "name": "Knapsack",
+ "uuid": "5bfffdf2-95d9-4794-b703-340c253400b2",
+ "practices": [],
+ "prerequisites": [],
+ "difficulty": 5
}
],
"foregone": [
diff --git a/exercises/practice/knapsack/.config/dotnet-tools.json b/exercises/practice/knapsack/.config/dotnet-tools.json
new file mode 100644
index 000000000..0f7926bad
--- /dev/null
+++ b/exercises/practice/knapsack/.config/dotnet-tools.json
@@ -0,0 +1,12 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "fantomas-tool": {
+ "version": "4.7.9",
+ "commands": [
+ "fantomas"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/exercises/practice/knapsack/.docs/instructions.md b/exercises/practice/knapsack/.docs/instructions.md
new file mode 100644
index 000000000..3411db988
--- /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 his 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.
+Bob 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, Bob should take the second and fourth item to maximize his value, which, in this case, is 90.
+He cannot get more than 90 as his 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..9b2bed8b4
--- /dev/null
+++ b/exercises/practice/knapsack/.docs/introduction.md
@@ -0,0 +1,8 @@
+# Introduction
+
+Bob is a thief.
+After months of careful planning, he finally manages to crack the security systems of a fancy store.
+
+In front of him are many items, each with a value and weight.
+Bob would gladly take all of the items, but his knapsack can only hold so much weight.
+Bob has to carefully consider which items to take so that the total value of his selection is maximized.
diff --git a/exercises/practice/knapsack/.meta/Example.fs b/exercises/practice/knapsack/.meta/Example.fs
new file mode 100644
index 000000000..8e381865c
--- /dev/null
+++ b/exercises/practice/knapsack/.meta/Example.fs
@@ -0,0 +1,13 @@
+module Knapsack
+
+type Item = { weight: int; value: int }
+
+let rec maximumValue items maximumWeight =
+ match items with
+ | [] -> 0
+ | item :: rest when item.weight > maximumWeight -> maximumValue rest maximumWeight
+ | item :: rest ->
+ max
+ (maximumValue rest maximumWeight)
+ (item.value
+ + maximumValue rest (maximumWeight - item.weight))
diff --git a/exercises/practice/knapsack/.meta/config.json b/exercises/practice/knapsack/.meta/config.json
new file mode 100644
index 000000000..4db8d25e4
--- /dev/null
+++ b/exercises/practice/knapsack/.meta/config.json
@@ -0,0 +1,19 @@
+{
+ "authors": [
+ "erikschierboom"
+ ],
+ "files": {
+ "solution": [
+ "Knapsack.fs"
+ ],
+ "test": [
+ "KnapsackTests.fs"
+ ],
+ "example": [
+ ".meta/Example.fs"
+ ]
+ },
+ "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/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/Knapsack.fs b/exercises/practice/knapsack/Knapsack.fs
new file mode 100644
index 000000000..e867f30b5
--- /dev/null
+++ b/exercises/practice/knapsack/Knapsack.fs
@@ -0,0 +1,6 @@
+module Knapsack
+
+type Item = { weight: int; value: int }
+
+let rec maximumValue items maximumWeight =
+ failwith "Please implement the 'maximumValue' function"
diff --git a/exercises/practice/knapsack/Knapsack.fsproj b/exercises/practice/knapsack/Knapsack.fsproj
new file mode 100644
index 000000000..63024204e
--- /dev/null
+++ b/exercises/practice/knapsack/Knapsack.fsproj
@@ -0,0 +1,22 @@
+
+
+ net8.0
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
\ No newline at end of file
diff --git a/exercises/practice/knapsack/KnapsackTests.fs b/exercises/practice/knapsack/KnapsackTests.fs
new file mode 100644
index 000000000..1da45f628
--- /dev/null
+++ b/exercises/practice/knapsack/KnapsackTests.fs
@@ -0,0 +1,81 @@
+module KnapsackTests
+
+open FsUnit.Xunit
+open Xunit
+
+open Knapsack
+
+[]
+let ``No items`` () = maximumValue [] 100 |> should equal 0
+
+[]
+let ``One item, too heavy`` () =
+ maximumValue [ { weight = 100; value = 1 } ] 10
+ |> should equal 0
+
+[]
+let ``Five items (cannot be greedy by weight)`` () =
+ maximumValue
+ [ { weight = 2; value = 5 }
+ { weight = 2; value = 5 }
+ { weight = 2; value = 5 }
+ { weight = 2; value = 5 }
+ { weight = 10; value = 21 } ]
+ 10
+ |> should equal 21
+
+[]
+let ``Five items (cannot be greedy by value)`` () =
+ maximumValue
+ [ { weight = 2; value = 20 }
+ { weight = 2; value = 20 }
+ { weight = 2; value = 20 }
+ { weight = 2; value = 20 }
+ { weight = 10; value = 50 } ]
+ 10
+ |> should equal 80
+
+[]
+let ``Example knapsack`` () =
+ maximumValue
+ [ { weight = 5; value = 10 }
+ { weight = 4; value = 40 }
+ { weight = 6; value = 30 }
+ { weight = 4; value = 50 } ]
+ 10
+ |> should equal 90
+
+[]
+let ``8 items`` () =
+ maximumValue
+ [ { 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 } ]
+ 104
+ |> should equal 900
+
+[]
+let ``15 items`` () =
+ maximumValue
+ [ { 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 } ]
+ 750
+ |> should equal 1458
diff --git a/generators/Generators.fs b/generators/Generators.fs
index cdaef5f31..8e44dfa01 100644
--- a/generators/Generators.fs
+++ b/generators/Generators.fs
@@ -2041,3 +2041,6 @@ type SquareRoot() =
type EliudsEggs() =
inherit ExerciseGenerator()
+
+type Knapsack() =
+ inherit ExerciseGenerator()