From 49019e7fe110aef398414524f08c4941a0896a42 Mon Sep 17 00:00:00 2001 From: colinleach Date: Tue, 1 Oct 2024 08:33:12 -0700 Subject: [PATCH 1/5] knapsack: add exercise --- config.json | 8 ++ .../practice/knapsack/.docs/instructions.md | 25 ++++++ .../practice/knapsack/.docs/introduction.md | 8 ++ exercises/practice/knapsack/.meta/config.json | 19 +++++ exercises/practice/knapsack/.meta/example.R | 28 +++++++ exercises/practice/knapsack/.meta/tests.toml | 36 +++++++++ exercises/practice/knapsack/knapsack.R | 3 + exercises/practice/knapsack/test_knapsack.R | 80 +++++++++++++++++++ 8 files changed, 207 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.R create mode 100644 exercises/practice/knapsack/.meta/tests.toml create mode 100644 exercises/practice/knapsack/knapsack.R create mode 100644 exercises/practice/knapsack/test_knapsack.R diff --git a/config.json b/config.json index 70a3c6df..2f0a8e07 100644 --- a/config.json +++ b/config.json @@ -672,6 +672,14 @@ "practices": [], "prerequisites": [], "difficulty": 1 + }, + { + "slug": "knapsack", + "name": "Knapsack", + "uuid": "cfd8e973-fd62-4ffe-8e16-faa5e34a6340", + "practices": [], + "prerequisites": [], + "difficulty": 5 } ] }, diff --git a/exercises/practice/knapsack/.docs/instructions.md b/exercises/practice/knapsack/.docs/instructions.md new file mode 100644 index 00000000..3411db98 --- /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 00000000..9b2bed8b --- /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/config.json b/exercises/practice/knapsack/.meta/config.json new file mode 100644 index 00000000..96624d5f --- /dev/null +++ b/exercises/practice/knapsack/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "colinleach" + ], + "files": { + "solution": [ + "knapsack.R" + ], + "test": [ + "test_knapsack.R" + ], + "example": [ + ".meta/example.R" + ] + }, + "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.R b/exercises/practice/knapsack/.meta/example.R new file mode 100644 index 00000000..40ad2087 --- /dev/null +++ b/exercises/practice/knapsack/.meta/example.R @@ -0,0 +1,28 @@ +maximum_value <- function(max_wt, items) { + # This URL is > 80 chars, ignore whining from the linter: + # https://en.wikipedia.org/wiki/Knapsack_problem#Dynamic_programming_in-advance_algorithm + + num_items <- length(items) + if (num_items == 0) return(0) + + # Remember, Julia uses 1-based array indexing + # so maxes[r,c] indexing needs to be r+1, c+1, compared to the Wiki reference + + maxes <- matrix(0, nrow = num_items + 1, ncol = max_wt + 1) + for (item in 1:num_items) { + for (weight in 1:max_wt) { + curr_wt <- items[[item]]$weight + if (curr_wt > weight) { + # copy the row above, the new item is no use to us + maxes[item + 1, weight + 1] <- maxes[item, weight + 1] + } else { + # perhaps drop an old item, add the new one? + drop_last <- maxes[item, weight - curr_wt + 1] + items[[item]]$value + maxes[item + 1, weight + 1] <- max(maxes[item, weight + 1], drop_last) + } + } + } + # maxes[nrow(maxes), ncol(maxes)] + # shorter way to get the bottom-right element: + tail(c(maxes), 1) +} diff --git a/exercises/practice/knapsack/.meta/tests.toml b/exercises/practice/knapsack/.meta/tests.toml new file mode 100644 index 00000000..8e013ef1 --- /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.R b/exercises/practice/knapsack/knapsack.R new file mode 100644 index 00000000..12c587e6 --- /dev/null +++ b/exercises/practice/knapsack/knapsack.R @@ -0,0 +1,3 @@ +maximum_value <- function(max_wt, items) { + +} diff --git a/exercises/practice/knapsack/test_knapsack.R b/exercises/practice/knapsack/test_knapsack.R new file mode 100644 index 00000000..8f08133a --- /dev/null +++ b/exercises/practice/knapsack/test_knapsack.R @@ -0,0 +1,80 @@ +source("./knapsack.R") +library(testthat) + +test_that("no items", { + expect_equal(maximum_value(100, list()), 0) +}) + +test_that("one item, too heavy", { + items <- list( + list(weight=100, value=1) + ) + expect_equal(maximum_value(10, items), 0) +}) + +test_that("five items (cannot be greedy by weight)" , { + items <- list( + list(weight=2, value=5), + list(weight=2, value=5), + list(weight=2, value=5), + list(weight=2, value=5), + list(weight=10, value=21) + ) + expect_equal(maximum_value(10, items), 21) +}) + +test_that("five items (cannot be greedy by value)", { + items <- list( + list(weight=2, value=20), + list(weight=2, value=20), + list(weight=2, value=20), + list(weight=2, value=20), + list(weight=10, value=50) + ) + expect_equal(maximum_value(10, items), 80) +}) + +test_that("example knapsack", { + items <- list( + list(weight=5, value=10), + list(weight=4, value=40), + list(weight=6, value=30), + list(weight=4, value=50) + ) + expect_equal(maximum_value(10, items), 90) +}) + +test_that("8 items", { + items <- list( + list(weight=25, value=350), + list(weight=35, value=400), + list(weight=45, value=450), + list(weight=5, value=20), + list(weight=25, value=70), + list(weight=3, value=8), + list(weight=2, value=5), + list(weight=2, value=5) + ) + expect_equal(maximum_value(104, items), 900) +}) + +test_that("15 items", { + items <- list( + list(weight=70, value=135), + list(weight=73, value=139), + list(weight=77, value=149), + list(weight=80, value=150), + list(weight=82, value=156), + list(weight=87, value=163), + list(weight=90, value=173), + list(weight=94, value=184), + list(weight=98, value=192), + list(weight=106, value=201), + list(weight=110, value=210), + list(weight=113, value=214), + list(weight=115, value=221), + list(weight=118, value=229), + list(weight=120, value=240) + ) + expect_equal(maximum_value(750, items), 1458) +}) From a5960b269ef840a2b7c134c977d0d14afb4bbe24 Mon Sep 17 00:00:00 2001 From: colinleach Date: Tue, 1 Oct 2024 08:44:32 -0700 Subject: [PATCH 2/5] fixed some linter issues --- exercises/practice/knapsack/test_knapsack.R | 78 ++++++++++----------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/exercises/practice/knapsack/test_knapsack.R b/exercises/practice/knapsack/test_knapsack.R index 8f08133a..4e8bab16 100644 --- a/exercises/practice/knapsack/test_knapsack.R +++ b/exercises/practice/knapsack/test_knapsack.R @@ -7,74 +7,74 @@ test_that("no items", { test_that("one item, too heavy", { items <- list( - list(weight=100, value=1) + list(weight = 100, value = 1) ) expect_equal(maximum_value(10, items), 0) }) -test_that("five items (cannot be greedy by weight)" , { +test_that("five items (cannot be greedy by weight)", { items <- list( - list(weight=2, value=5), - list(weight=2, value=5), - list(weight=2, value=5), - list(weight=2, value=5), - list(weight=10, value=21) + list(weight = 2, value = 5), + list(weight = 2, value = 5), + list(weight = 2, value = 5), + list(weight = 2, value = 5), + list(weight = 10, value = 21) ) expect_equal(maximum_value(10, items), 21) }) test_that("five items (cannot be greedy by value)", { items <- list( - list(weight=2, value=20), - list(weight=2, value=20), - list(weight=2, value=20), - list(weight=2, value=20), - list(weight=10, value=50) + list(weight = 2, value = 20), + list(weight = 2, value = 20), + list(weight = 2, value = 20), + list(weight = 2, value = 20), + list(weight = 10, value = 50) ) expect_equal(maximum_value(10, items), 80) }) test_that("example knapsack", { items <- list( - list(weight=5, value=10), - list(weight=4, value=40), - list(weight=6, value=30), - list(weight=4, value=50) + list(weight = 5, value = 10), + list(weight = 4, value = 40), + list(weight = 6, value = 30), + list(weight = 4, value = 50) ) expect_equal(maximum_value(10, items), 90) }) test_that("8 items", { items <- list( - list(weight=25, value=350), - list(weight=35, value=400), - list(weight=45, value=450), - list(weight=5, value=20), - list(weight=25, value=70), - list(weight=3, value=8), - list(weight=2, value=5), - list(weight=2, value=5) + list(weight = 25, value = 350), + list(weight = 35, value = 400), + list(weight = 45, value = 450), + list(weight = 5, value = 20), + list(weight = 25, value = 70), + list(weight = 3, value = 8), + list(weight = 2, value = 5), + list(weight = 2, value = 5) ) expect_equal(maximum_value(104, items), 900) }) test_that("15 items", { items <- list( - list(weight=70, value=135), - list(weight=73, value=139), - list(weight=77, value=149), - list(weight=80, value=150), - list(weight=82, value=156), - list(weight=87, value=163), - list(weight=90, value=173), - list(weight=94, value=184), - list(weight=98, value=192), - list(weight=106, value=201), - list(weight=110, value=210), - list(weight=113, value=214), - list(weight=115, value=221), - list(weight=118, value=229), - list(weight=120, value=240) + list(weight = 70, value = 135), + list(weight = 73, value = 139), + list(weight = 77, value = 149), + list(weight = 80, value = 150), + list(weight = 82, value = 156), + list(weight = 87, value = 163), + list(weight = 90, value = 173), + list(weight = 94, value = 184), + list(weight = 98, value = 192), + list(weight = 106, value = 201), + list(weight = 110, value = 210), + list(weight = 113, value = 214), + list(weight = 115, value = 221), + list(weight = 118, value = 229), + list(weight = 120, value = 240) ) expect_equal(maximum_value(750, items), 1458) }) From c461d28a3833dfb3e6a1dcb3654895472564c7ce Mon Sep 17 00:00:00 2001 From: colinleach Date: Wed, 16 Oct 2024 08:59:01 -0500 Subject: [PATCH 3/5] Update exercises/practice/knapsack/knapsack.R Co-authored-by: Erik Schierboom --- exercises/practice/knapsack/knapsack.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/knapsack/knapsack.R b/exercises/practice/knapsack/knapsack.R index 12c587e6..592df693 100644 --- a/exercises/practice/knapsack/knapsack.R +++ b/exercises/practice/knapsack/knapsack.R @@ -1,3 +1,3 @@ -maximum_value <- function(max_wt, items) { +maximum_value <- function(max_weight, items) { } From adbb6b72323e50411467eb3c778c83abab1f8fd1 Mon Sep 17 00:00:00 2001 From: colinleach Date: Wed, 16 Oct 2024 08:59:15 -0500 Subject: [PATCH 4/5] Update exercises/practice/knapsack/.meta/example.R Co-authored-by: Erik Schierboom --- exercises/practice/knapsack/.meta/example.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/practice/knapsack/.meta/example.R b/exercises/practice/knapsack/.meta/example.R index 40ad2087..3ac8b7f4 100644 --- a/exercises/practice/knapsack/.meta/example.R +++ b/exercises/practice/knapsack/.meta/example.R @@ -1,6 +1,8 @@ maximum_value <- function(max_wt, items) { # This URL is > 80 chars, ignore whining from the linter: + # nolint start # https://en.wikipedia.org/wiki/Knapsack_problem#Dynamic_programming_in-advance_algorithm + # nolint end num_items <- length(items) if (num_items == 0) return(0) From 8a1d982ff10fd674b2e7023ea439706573a9cc6d Mon Sep 17 00:00:00 2001 From: colinleach Date: Wed, 16 Oct 2024 09:03:14 -0500 Subject: [PATCH 5/5] Update example.R --- exercises/practice/knapsack/.meta/example.R | 1 - 1 file changed, 1 deletion(-) diff --git a/exercises/practice/knapsack/.meta/example.R b/exercises/practice/knapsack/.meta/example.R index 3ac8b7f4..3a1832f8 100644 --- a/exercises/practice/knapsack/.meta/example.R +++ b/exercises/practice/knapsack/.meta/example.R @@ -1,5 +1,4 @@ maximum_value <- function(max_wt, items) { - # This URL is > 80 chars, ignore whining from the linter: # nolint start # https://en.wikipedia.org/wiki/Knapsack_problem#Dynamic_programming_in-advance_algorithm # nolint end