diff --git a/config.json b/config.json
index 9d5eb722..d746ae2e 100644
--- a/config.json
+++ b/config.json
@@ -368,7 +368,15 @@
"practices": [],
"prerequisites": [],
"difficulty": 3
- }
+ },
+ {
+ "slug": "knapsack",
+ "name": "Knapsack",
+ "uuid": "2f9877d5-eec5-4048-a868-975d028147ef",
+ "practices": [],
+ "prerequisites": [],
+ "difficulty": 5
+ }
]
},
"concepts": [
diff --git a/exercises/practice/knapsack/.docs/instructions.md b/exercises/practice/knapsack/.docs/instructions.md
new file mode 100644
index 00000000..1dbbca91
--- /dev/null
+++ b/exercises/practice/knapsack/.docs/instructions.md
@@ -0,0 +1,32 @@
+# Instructions
+
+In this exercise, let's try to solve a classic problem.
+
+Bob is a thief.
+After months of careful planning, he finally manages to crack the security systems of a high-class apartment.
+
+In front of him are many items, each with a value (v) and weight (w).
+Bob, of course, wants to maximize the total value he can get; he would gladly take all of the items if he could.
+However, to his horror, he realizes that the knapsack he carries with him can only hold so much weight (W).
+
+Given a knapsack with a specific carrying capacity (W), help Bob determine the maximum value he can get from the items in the house.
+Note that Bob can take only one of each item.
+
+All values given will be strictly positive.
+Items will be represented as a list of pairs, `wi` and `vi`, where the first element `wi` is the weight of the *i*th item and `vi` is the value for that item.
+
+For example:
+
+Items: [
+ { "weight": 5, "value": 10 },
+ { "weight": 4, "value": 40 },
+ { "weight": 6, "value": 30 },
+ { "weight": 4, "value": 50 }
+]
+
+Knapsack Limit: 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/.meta/config.json b/exercises/practice/knapsack/.meta/config.json
new file mode 100644
index 00000000..0c57d590
--- /dev/null
+++ b/exercises/practice/knapsack/.meta/config.json
@@ -0,0 +1,17 @@
+{
+ "authors": [],
+ "files": {
+ "solution": [
+ "zcl_knapsack.clas.abap"
+ ],
+ "test": [
+ "zcl_knapsack.clas.testclasses.abap"
+ ],
+ "example": [
+ ".meta/zcl_knapsack.clas.abap"
+ ]
+ },
+ "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/zcl_knapsack.clas.abap b/exercises/practice/knapsack/.meta/zcl_knapsack.clas.abap
new file mode 100644
index 00000000..c6b2636d
--- /dev/null
+++ b/exercises/practice/knapsack/.meta/zcl_knapsack.clas.abap
@@ -0,0 +1,64 @@
+CLASS zcl_knapsack DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+
+ TYPES: BEGIN OF item_type,
+ weight TYPE i,
+ value TYPE i,
+ END OF item_type.
+ TYPES items_type TYPE TABLE OF item_type.
+
+ METHODS get_max_possible_value
+ IMPORTING weight_limit TYPE i
+ items TYPE items_type
+ RETURNING VALUE(max_value) TYPE i.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ENDCLASS.
+
+
+
+CLASS zcl_knapsack IMPLEMENTATION.
+
+
+ METHOD get_max_possible_value.
+
+ TYPES int_table TYPE STANDARD TABLE OF i WITH NON-UNIQUE KEY table_line.
+ DATA matrix TYPE STANDARD TABLE OF int_table.
+
+ " Implementation of dynamic programming approach
+ " https://en.wikipedia.org/wiki/Knapsack_problem#0-1_knapsack_problem
+
+ DO lines( items ) + 1 TIMES.
+ APPEND VALUE #( ) TO matrix REFERENCE INTO DATA(item_line).
+ DO weight_limit + 1 TIMES.
+ APPEND VALUE #( ) TO item_line->*.
+ ENDDO.
+ ENDDO.
+
+ DATA i TYPE i VALUE 2.
+ DATA j TYPE i.
+
+ DO lines( items ) TIMES.
+ j = 1.
+ DO weight_limit + 1 TIMES.
+ " Include current item only if it yields a value increase
+ " Including item is only an option if current weight limit is met
+ matrix[ i ][ j ] = nmax( val1 = matrix[ i - 1 ][ j ]
+ val2 = COND i( WHEN items[ i - 1 ]-weight <= j - 1
+ THEN matrix[ i - 1 ][ j - items[ i - 1 ]-weight ]
+ + items[ i - 1 ]-value
+ ELSE 0 ) ).
+ j += 1.
+ ENDDO.
+ i += 1.
+ ENDDO.
+
+ max_value = matrix[ lines( items ) + 1 ][ weight_limit + 1 ].
+
+ ENDMETHOD.
+ENDCLASS.
diff --git a/exercises/practice/knapsack/package.devc.xml b/exercises/practice/knapsack/package.devc.xml
new file mode 100644
index 00000000..5c226240
--- /dev/null
+++ b/exercises/practice/knapsack/package.devc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+ Exercism: Knapsack
+
+
+
+
diff --git a/exercises/practice/knapsack/zcl_knapsack.clas.abap b/exercises/practice/knapsack/zcl_knapsack.clas.abap
new file mode 100644
index 00000000..a795d5ec
--- /dev/null
+++ b/exercises/practice/knapsack/zcl_knapsack.clas.abap
@@ -0,0 +1,31 @@
+CLASS zcl_knapsack DEFINITION
+ PUBLIC
+ FINAL
+ CREATE PUBLIC .
+
+ PUBLIC SECTION.
+
+ TYPES: BEGIN OF item_type,
+ weight TYPE i,
+ value TYPE i,
+ END OF item_type.
+ TYPES items_type TYPE TABLE OF item_type.
+
+ METHODS get_max_possible_value
+ IMPORTING weight_limit TYPE i
+ items TYPE items_type
+ RETURNING VALUE(max_value) TYPE i.
+
+ PROTECTED SECTION.
+ PRIVATE SECTION.
+ENDCLASS.
+
+
+
+CLASS zcl_knapsack IMPLEMENTATION.
+
+ METHOD get_max_possible_value.
+ " add solution here
+ ENDMETHOD.
+
+ENDCLASS.
diff --git a/exercises/practice/knapsack/zcl_knapsack.clas.testclasses.abap b/exercises/practice/knapsack/zcl_knapsack.clas.testclasses.abap
new file mode 100644
index 00000000..c98bb1f7
--- /dev/null
+++ b/exercises/practice/knapsack/zcl_knapsack.clas.testclasses.abap
@@ -0,0 +1,111 @@
+CLASS ltcl_knapsack DEFINITION FINAL FOR TESTING
+ DURATION SHORT
+ RISK LEVEL HARMLESS.
+
+ PRIVATE SECTION.
+
+ DATA cut TYPE REF TO zcl_knapsack.
+
+ METHODS setup.
+
+ METHODS no_items FOR TESTING RAISING cx_static_check.
+ METHODS one_item_too_heavy FOR TESTING RAISING cx_static_check.
+ "! five items (cannot be greedy by weight)
+ METHODS five_items_cannot_be_greedy_1 FOR TESTING RAISING cx_static_check.
+ "! five items (cannot be greedy by value)
+ METHODS five_items_cannot_be_greedy_2 FOR TESTING RAISING cx_static_check.
+ METHODS example_knapsack FOR TESTING RAISING cx_static_check.
+ METHODS eight_items FOR TESTING RAISING cx_static_check.
+ METHODS fifteen_items FOR TESTING RAISING cx_static_check.
+
+ENDCLASS.
+
+
+CLASS ltcl_knapsack IMPLEMENTATION.
+
+ METHOD setup.
+ cut = NEW #( ).
+ ENDMETHOD.
+
+ METHOD no_items.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 0
+ act = cut->get_max_possible_value( weight_limit = 100
+ items = VALUE #( ) ) ).
+ ENDMETHOD.
+
+ METHOD one_item_too_heavy.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 0
+ act = cut->get_max_possible_value( weight_limit = 10
+ items = VALUE #( ( weight = 100 value = 1 ) ) ) ).
+ ENDMETHOD.
+
+ METHOD five_items_cannot_be_greedy_1.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 21
+ act = cut->get_max_possible_value( weight_limit = 10
+ items = VALUE #( ( weight = 2 value = 5 )
+ ( weight = 2 value = 5 )
+ ( weight = 2 value = 5 )
+ ( weight = 2 value = 5 )
+ ( weight = 10 value = 21 ) ) ) ).
+ ENDMETHOD.
+
+ METHOD five_items_cannot_be_greedy_2.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 80
+ act = cut->get_max_possible_value( weight_limit = 10
+ items = VALUE #( ( weight = 2 value = 20 )
+ ( weight = 2 value = 20 )
+ ( weight = 2 value = 20 )
+ ( weight = 2 value = 20 )
+ ( weight = 10 value = 50 ) ) ) ).
+ ENDMETHOD.
+
+ METHOD example_knapsack.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 90
+ act = cut->get_max_possible_value( weight_limit = 10
+ items = VALUE #( ( weight = 5 value = 10 )
+ ( weight = 4 value = 40 )
+ ( weight = 6 value = 30 )
+ ( weight = 4 value = 50 ) ) ) ).
+ ENDMETHOD.
+
+ METHOD eight_items.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 900
+ act = cut->get_max_possible_value( weight_limit = 104
+ items = VALUE #( ( 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 ) ) ) ).
+ ENDMETHOD.
+
+ METHOD fifteen_items.
+ cl_abap_unit_assert=>assert_equals(
+ exp = 1458
+ act = cut->get_max_possible_value( weight_limit = 750
+ items = VALUE #( ( 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 ) ) ) ).
+ ENDMETHOD.
+
+ENDCLASS.
diff --git a/exercises/practice/knapsack/zcl_knapsack.clas.xml b/exercises/practice/knapsack/zcl_knapsack.clas.xml
new file mode 100644
index 00000000..1a07ad1f
--- /dev/null
+++ b/exercises/practice/knapsack/zcl_knapsack.clas.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+ ZCL_KNAPSACK
+ E
+ Exercism: Knapsack
+ 1
+ X
+ X
+ X
+ X
+
+
+
+