Skip to content

Commit aed5d86

Browse files
authored
Merge branch 'master' into feat/rabin-karp-sgindeed
2 parents b72730f + 96737fe commit aed5d86

File tree

3 files changed

+322
-0
lines changed

3 files changed

+322
-0
lines changed
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
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+
28+
# Handle edge case
29+
if (n == 0 || capacity == 0) {
30+
return(list(
31+
max_value = 0,
32+
selected_items = c(),
33+
dp_table = matrix(0, nrow = n + 1, ncol = capacity + 1)
34+
))
35+
}
36+
37+
# Create DP table: dp[i, w] = max value using first i items with capacity w
38+
dp <- matrix(0, nrow = n + 1, ncol = capacity + 1)
39+
40+
# Fill DP table
41+
for (i in 1:n) {
42+
for (w in 0:capacity) {
43+
# Don't include item i
44+
dp[i + 1, w + 1] <- dp[i, w + 1]
45+
46+
# Include item i (if it fits)
47+
if (weights[i] <= w) {
48+
include_value <- values[i] + dp[i, w - weights[i] + 1]
49+
dp[i + 1, w + 1] <- max(dp[i + 1, w + 1], include_value)
50+
}
51+
}
52+
}
53+
54+
# Backtrack to find selected items
55+
selected <- c()
56+
i <- n
57+
w <- capacity
58+
59+
while (i > 0 && w > 0) {
60+
# If value came from including item i
61+
if (dp[i + 1, w + 1] != dp[i, w + 1]) {
62+
selected <- c(i, selected)
63+
w <- w - weights[i]
64+
}
65+
i <- i - 1
66+
}
67+
68+
return(list(
69+
max_value = dp[n + 1, capacity + 1],
70+
selected_items = selected,
71+
dp_table = dp
72+
))
73+
}
74+
75+
# Space-optimized version using only 1D array
76+
knapsack_01_optimized <- function(weights, values, capacity) {
77+
#' Space optimized 0/1 Knapsack using 1D array
78+
#' @return: Maximum total value
79+
80+
n <- length(values)
81+
82+
if (n == 0 || capacity == 0) {
83+
return(0)
84+
}
85+
86+
dp <- rep(0, capacity + 1)
87+
88+
# Process each item
89+
for (i in 1:n) {
90+
# Traverse from right to left to avoid overwriting needed values
91+
for (w in capacity:weights[i]) {
92+
if (weights[i] <= w) {
93+
dp[w + 1] <- max(dp[w + 1], values[i] + dp[w - weights[i] + 1])
94+
}
95+
}
96+
}
97+
98+
return(dp[capacity + 1])
99+
}
100+
101+
# Helper function to print DP table
102+
print_knapsack_dp <- function(dp_table, weights, values, capacity) {
103+
cat("DP Table for 0/1 Knapsack:\n")
104+
cat("Weights:", paste(weights, collapse = ", "), "\n")
105+
cat("Values :", paste(values, collapse = ", "), "\n")
106+
cat("Capacity:", capacity, "\n\n")
107+
108+
# Print capacity headers
109+
cat(" ")
110+
cat(paste(sprintf("%3d", 0:capacity), collapse = " "))
111+
cat("\n")
112+
cat(paste(rep("-", 8 + 4 * (capacity + 1)), collapse = ""), "\n")
113+
114+
for (i in 1:nrow(dp_table)) {
115+
cat(sprintf("Item %2d | ", i - 1))
116+
cat(paste(sprintf("%3d", dp_table[i, ]), collapse = " "))
117+
cat("\n")
118+
}
119+
cat("\n")
120+
}
121+
122+
# ===========================
123+
# Example Usage & Testing
124+
# ===========================
125+
cat("=== 0/1 Knapsack Problem (Dynamic Programming) ===\n\n")
126+
127+
# Test 1: Basic Example
128+
weights <- c(1, 3, 4, 5)
129+
values <- c(1, 4, 5, 7)
130+
capacity <- 7
131+
132+
cat("Test 1: Basic Example\n")
133+
cat("Weights:", paste(weights, collapse = ", "), "\n")
134+
cat("Values :", paste(values, collapse = ", "), "\n")
135+
cat("Capacity:", capacity, "\n\n")
136+
137+
result <- knapsack_01(weights, values, capacity)
138+
print_knapsack_dp(result$dp_table, weights, values, capacity)
139+
cat("Maximum Value:", result$max_value, "\n")
140+
cat("Selected Item Indices:", paste(result$selected_items, collapse = ", "), "\n")
141+
cat("Total Weight:", sum(weights[result$selected_items]), "\n")
142+
cat("Total Value:", sum(values[result$selected_items]), "\n\n")
143+
144+
# Test 2: Space Optimized Example
145+
cat("Test 2: Space Optimized Version\n")
146+
max_val_opt <- knapsack_01_optimized(weights, values, capacity)
147+
cat("Maximum Value (Optimized):", max_val_opt, "\n")
148+
cat("Verification: Both methods match:", result$max_value == max_val_opt, "\n\n")
149+
150+
# Test 3: Larger Dataset
151+
cat("Test 3: Larger Dataset\n")
152+
set.seed(42)
153+
weights <- sample(1:15, 10)
154+
values <- sample(10:100, 10)
155+
capacity <- 35
156+
157+
cat("Weights:", paste(weights, collapse = ", "), "\n")
158+
cat("Values :", paste(values, collapse = ", "), "\n")
159+
cat("Capacity:", capacity, "\n\n")
160+
161+
large_result <- knapsack_01(weights, values, capacity)
162+
cat("Maximum Value:", large_result$max_value, "\n")
163+
cat("Selected Items:", paste(large_result$selected_items, collapse = ", "), "\n")
164+
cat("Total Weight:", sum(weights[large_result$selected_items]), "\n\n")
165+
166+
# Test 4: Edge Cases
167+
cat("Test 4: Edge Cases\n")
168+
cat("Empty items:", knapsack_01(c(), c(), 10)$max_value, "\n")
169+
cat("Zero capacity:", knapsack_01(weights, values, 0)$max_value, "\n")
170+
cat("Single item fits:", knapsack_01(c(5), c(10), 10)$max_value, "\n")
171+
cat("Single item doesn't fit:", knapsack_01(c(10), c(10), 5)$max_value, "\n\n")
172+
173+
# Test 5: Performance Check
174+
cat("Test 5: Performance Comparison (n=100)\n")
175+
n <- 100
176+
weights <- sample(1:15, n, replace = TRUE)
177+
values <- sample(10:100, n, replace = TRUE)
178+
capacity <- 200
179+
180+
start_time <- Sys.time()
181+
res_std <- knapsack_01_optimized(weights, values, capacity)
182+
std_time <- as.numeric(Sys.time() - start_time, units = "secs")
183+
184+
cat("Optimized DP result:", res_std, "\n")
185+
cat("Time taken:", sprintf("%.4f sec", std_time), "\n")
186+
187+
# Verify correctness
188+
cat("\nVerifying correctness with full DP:\n")
189+
start_time <- Sys.time()
190+
res_full <- knapsack_01(weights, values, capacity)
191+
full_time <- as.numeric(Sys.time() - start_time, units = "secs")
192+
cat("Full DP result:", res_full$max_value, "\n")
193+
cat("Time taken:", sprintf("%.4f sec", full_time), "\n")
194+
cat("Results match:", res_std == res_full$max_value, "\n")
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Longest Palindromic Subsequence in R
2+
# Author: sgindeed
3+
# Description: Finds and prints the longest palindromic subsequence and its length
4+
5+
# Ask for user input
6+
input.string <- readline(prompt = "Enter a string: ")
7+
8+
# Convert string to lowercase for consistency
9+
clean.string <- tolower(input.string)
10+
11+
# Get length of string
12+
n <- nchar(clean.string)
13+
14+
# Split string into characters
15+
chars <- strsplit(clean.string, "")[[1]]
16+
17+
# Initialize DP table for lengths
18+
dp <- matrix(0, nrow = n, ncol = n)
19+
20+
# Each single character is a palindrome of length 1
21+
for (i in seq_len(n)) {
22+
dp[i, i] <- 1
23+
}
24+
25+
# Fill the DP table
26+
for (cl in 2:n) {
27+
for (i in 1:(n - cl + 1)) {
28+
j <- i + cl - 1
29+
if (chars[i] == chars[j] && cl == 2) {
30+
dp[i, j] <- 2
31+
} else if (chars[i] == chars[j]) {
32+
dp[i, j] <- dp[i + 1, j - 1] + 2
33+
} else {
34+
dp[i, j] <- max(dp[i + 1, j], dp[i, j - 1])
35+
}
36+
}
37+
}
38+
39+
# Function to reconstruct the subsequence
40+
reconstructLPS <- function(chars, dp, i, j) {
41+
if (i > j) {
42+
return("")
43+
}
44+
if (i == j) {
45+
return(chars[i])
46+
}
47+
if (chars[i] == chars[j]) {
48+
return(paste0(chars[i], reconstructLPS(chars, dp, i + 1, j - 1), chars[j]))
49+
}
50+
if (dp[i + 1, j] > dp[i, j - 1]) {
51+
return(reconstructLPS(chars, dp, i + 1, j))
52+
} else {
53+
return(reconstructLPS(chars, dp, i, j - 1))
54+
}
55+
}
56+
57+
# Get the longest palindromic subsequence
58+
lps <- reconstructLPS(chars, dp, 1, n)
59+
60+
# Display the result
61+
cat("Longest Palindromic Subsequence:", lps, "\n")
62+
cat("Length:", nchar(lps), "\n")
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Minimum Window Substring in R
2+
# Author: sgindeed
3+
# Description: Finds the smallest substring of s that contains all characters of t
4+
5+
# Ask for inputs
6+
s <- readline(prompt = "Enter main string: ")
7+
t <- readline(prompt = "Enter target characters: ")
8+
9+
# Convert to lowercase for case-insensitivity
10+
s <- tolower(s)
11+
t <- tolower(t)
12+
13+
# Edge case
14+
if (nchar(s) == 0 || nchar(t) == 0) {
15+
cat("Empty input. Exiting.\n")
16+
quit(save = "no")
17+
}
18+
19+
# Convert to char arrays
20+
s_chars <- strsplit(s, "")[[1]]
21+
t_chars <- strsplit(t, "")[[1]]
22+
23+
# Frequency of characters in t
24+
t_count <- table(t_chars)
25+
window_count <- list()
26+
27+
required <- length(t_count)
28+
formed <- 0
29+
30+
left <- 1
31+
right <- 0
32+
min_len <- Inf
33+
min_window <- ""
34+
35+
# Sliding window
36+
while (right < length(s_chars)) {
37+
right <- right + 1
38+
char <- s_chars[right]
39+
window_count[[char]] <- (window_count[[char]] %||% 0) + 1
40+
41+
if (!is.na(t_count[char]) && window_count[[char]] == t_count[char]) {
42+
formed <- formed + 1
43+
}
44+
45+
# Try to contract the window
46+
while (left <= right && formed == required) {
47+
if ((right - left + 1) < min_len) {
48+
min_len <- right - left + 1
49+
min_window <- paste0(s_chars[left:right], collapse = "")
50+
}
51+
52+
left_char <- s_chars[left]
53+
window_count[[left_char]] <- window_count[[left_char]] - 1
54+
if (!is.na(t_count[left_char]) && window_count[[left_char]] < t_count[left_char]) {
55+
formed <- formed - 1
56+
}
57+
left <- left + 1
58+
}
59+
}
60+
61+
if (is.infinite(min_len)) {
62+
cat("No valid window found.\n")
63+
} else {
64+
cat("Minimum window substring:", min_window, "\n")
65+
cat("Length:", min_len, "\n")
66+
}

0 commit comments

Comments
 (0)