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 + + + +