Skip to content

Commit 1887b93

Browse files
authored
feat: implement Longest Increasing Subsequence algorithm in R (#169)
1 parent e5f6012 commit 1887b93

File tree

2 files changed

+404
-0
lines changed

2 files changed

+404
-0
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# 0/1 Knapsack Problem (Dynamic Programming)
2+
#
3+
# The 0/1 Knapsack problem is one of the most classic problems in dynamic programming.
4+
# Given a set of items, each with a weight and a value, determine the maximum total value
5+
# you can obtain by putting items in a knapsack with a fixed capacity. Each item can
6+
# either be included (1) or excluded (0) — hence the name "0/1".
7+
#
8+
# Time Complexity: O(n * W) where n = number of items, W = knapsack capacity
9+
# Space Complexity: O(n * W) for full DP table, O(W) for optimized version
10+
#
11+
# Applications:
12+
# - Budget allocation problems
13+
# - Resource optimization (CPU scheduling, project selection)
14+
# - Portfolio selection in finance
15+
# - Cargo loading and packing
16+
# - Subset optimization in AI planning
17+
18+
# Classic DP solution for 0/1 Knapsack
19+
knapsack_01 <- function(weights, values, capacity) {
20+
#' Solve 0/1 Knapsack Problem using Dynamic Programming
21+
#' @param weights: Numeric vector of item weights
22+
#' @param values: Numeric vector of item values
23+
#' @param capacity: Maximum weight capacity of the knapsack
24+
#' @return: List containing max value, selected items, and DP table
25+
26+
n <- length(values)
27+
dp <- matrix(0, nrow = n + 1, ncol = capacity + 1)
28+
29+
# Fill DP table
30+
for (i in 2:(n + 1)) {
31+
for (w in 0:capacity) {
32+
if (weights[i - 1] <= w) {
33+
include <- values[i - 1] + dp[i - 1, w - weights[i - 1] + 1]
34+
exclude <- dp[i - 1, w + 1]
35+
dp[i, w + 1] <- max(include, exclude)
36+
} else {
37+
dp[i, w + 1] <- dp[i - 1, w + 1]
38+
}
39+
}
40+
}
41+
42+
# Backtrack to find selected items
43+
res_value <- dp[n + 1, capacity + 1]
44+
selected <- c()
45+
w <- capacity
46+
47+
for (i in n:1) {
48+
if (res_value <= 0) break
49+
if (res_value == dp[i, w + 1]) next
50+
51+
# Item i is included
52+
selected <- c(i, selected)
53+
res_value <- res_value - values[i]
54+
w <- w - weights[i]
55+
}
56+
57+
return(list(
58+
max_value = dp[n + 1, capacity + 1],
59+
selected_items = selected,
60+
dp_table = dp
61+
))
62+
}
63+
64+
# Space-optimized version using only 1D array
65+
knapsack_01_optimized <- function(weights, values, capacity) {
66+
#' Space optimized 0/1 Knapsack using 1D array
67+
#' @return: Maximum total value
68+
69+
n <- length(values)
70+
dp <- rep(0, capacity + 1)
71+
72+
for (i in 1:n) {
73+
for (w in capacity:weights[i]) {
74+
dp[w + 1] <- max(dp[w + 1], values[i] + dp[w - weights[i] + 1])
75+
}
76+
}
77+
78+
return(dp[capacity + 1])
79+
}
80+
81+
# Helper function to print DP table
82+
print_knapsack_dp <- function(dp_table, weights, values, capacity) {
83+
cat("DP Table for 0/1 Knapsack:\n")
84+
cat("Weights:", paste(weights, collapse = ", "), "\n")
85+
cat("Values :", paste(values, collapse = ", "), "\n")
86+
cat("Capacity:", capacity, "\n\n")
87+
88+
for (i in 1:nrow(dp_table)) {
89+
cat(sprintf("Item %2d | ", i - 1))
90+
cat(paste(sprintf("%3d", dp_table[i, ]), collapse = " "))
91+
cat("\n")
92+
}
93+
cat("\n")
94+
}
95+
96+
# ===========================
97+
# Example Usage & Testing
98+
# ===========================
99+
cat("=== 0/1 Knapsack Problem (Dynamic Programming) ===\n\n")
100+
101+
# Test 1: Basic Example
102+
weights <- c(1, 3, 4, 5)
103+
values <- c(1, 4, 5, 7)
104+
capacity <- 7
105+
106+
cat("Test 1: Basic Example\n")
107+
cat("Weights:", paste(weights, collapse = ", "), "\n")
108+
cat("Values :", paste(values, collapse = ", "), "\n")
109+
cat("Capacity:", capacity, "\n\n")
110+
111+
result <- knapsack_01(weights, values, capacity)
112+
print_knapsack_dp(result$dp_table, weights, values, capacity)
113+
cat("Maximum Value:", result$max_value, "\n")
114+
cat("Selected Item Indices:", paste(result$selected_items, collapse = ", "), "\n\n")
115+
116+
# Test 2: Space Optimized Example
117+
cat("Test 2: Space Optimized Version\n")
118+
max_val_opt <- knapsack_01_optimized(weights, values, capacity)
119+
cat("Maximum Value (Optimized):", max_val_opt, "\n\n")
120+
121+
# Test 3: Larger Dataset
122+
cat("Test 3: Larger Dataset\n")
123+
set.seed(42)
124+
weights <- sample(1:15, 10)
125+
values <- sample(10:100, 10)
126+
capacity <- 35
127+
128+
cat("Weights:", paste(weights, collapse = ", "), "\n")
129+
cat("Values :", paste(values, collapse = ", "), "\n")
130+
cat("Capacity:", capacity, "\n\n")
131+
132+
large_result <- knapsack_01(weights, values, capacity)
133+
cat("Maximum Value:", large_result$max_value, "\n")
134+
cat("Selected Items:", paste(large_result$selected_items, collapse = ", "), "\n\n")
135+
136+
# Test 4: Edge Cases
137+
cat("Test 4: Edge Cases\n")
138+
cat("Empty items:", knapsack_01(c(), c(), 10)$max_value, "\n")
139+
cat("Zero capacity:", knapsack_01(weights, values, 0)$max_value, "\n")
140+
cat("Single item fits:", knapsack_01(c(5), c(10), 10)$max_value, "\n")
141+
cat("Single item doesn't fit:", knapsack_01(c(10), c(10), 5)$max_value, "\n\n")
142+
143+
# Test 5: Performance Check
144+
cat("Test 5: Performance Comparison (n=100)\n")
145+
n <- 100
146+
weights <- sample(1:15, n, replace = TRUE)
147+
values <- sample(10:100, n, replace = TRUE)
148+
capacity <- 200
149+
150+
start_time <- Sys.time()
151+
res_std <- knapsack_01_optimized(weights, values, capacity)
152+
std_time <- as.numeric(Sys.time() - start_time, units = "secs")
153+
154+
cat("Optimized DP result:", res_std, "\n")
155+
cat("Time taken:", sprintf("%.4f sec", std_time), "\n")

0 commit comments

Comments
 (0)