|
| 1 | +//! This module provides functionality to check if there exists a subset of a given set of integers |
| 2 | +//! that sums to a target value. The implementation uses a recursive backtracking approach. |
| 3 | +
|
| 4 | +/// Checks if there exists a subset of the given set that sums to the target value. |
| 5 | +pub fn has_subset_with_sum(set: &[isize], target: isize) -> bool { |
| 6 | + backtrack(set, set.len(), target) |
| 7 | +} |
| 8 | + |
| 9 | +fn backtrack(set: &[isize], remaining_items: usize, target: isize) -> bool { |
| 10 | + // Found a subset with the required sum |
| 11 | + if target == 0 { |
| 12 | + return true; |
| 13 | + } |
| 14 | + // No more elements to process |
| 15 | + if remaining_items == 0 { |
| 16 | + return false; |
| 17 | + } |
| 18 | + // Check if we can find a subset including or excluding the last element |
| 19 | + backtrack(set, remaining_items - 1, target) |
| 20 | + || backtrack(set, remaining_items - 1, target - set[remaining_items - 1]) |
| 21 | +} |
| 22 | + |
| 23 | +#[cfg(test)] |
| 24 | +mod tests { |
| 25 | + use super::*; |
| 26 | + |
| 27 | + macro_rules! has_subset_with_sum_tests { |
| 28 | + ($($name:ident: $test_case:expr,)*) => { |
| 29 | + $( |
| 30 | + #[test] |
| 31 | + fn $name() { |
| 32 | + let (set, target, expected) = $test_case; |
| 33 | + assert_eq!(has_subset_with_sum(set, target), expected); |
| 34 | + } |
| 35 | + )* |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + has_subset_with_sum_tests! { |
| 40 | + test_small_set_with_sum: (&[3, 34, 4, 12, 5, 2], 9, true), |
| 41 | + test_small_set_without_sum: (&[3, 34, 4, 12, 5, 2], 30, false), |
| 42 | + test_consecutive_set_with_sum: (&[1, 2, 3, 4, 5, 6], 10, true), |
| 43 | + test_consecutive_set_without_sum: (&[1, 2, 3, 4, 5, 6], 22, false), |
| 44 | + test_large_set_with_sum: (&[5, 10, 12, 13, 15, 18, -1, 10, 50, -2, 3, 4], 30, true), |
| 45 | + test_empty_set: (&[], 0, true), |
| 46 | + test_empty_set_with_nonzero_sum: (&[], 10, false), |
| 47 | + test_single_element_equal_to_sum: (&[10], 10, true), |
| 48 | + test_single_element_not_equal_to_sum: (&[5], 10, false), |
| 49 | + test_negative_set_with_sum: (&[-7, -3, -2, 5, 8], 0, true), |
| 50 | + test_negative_sum: (&[1, 2, 3, 4, 5], -1, false), |
| 51 | + test_negative_sum_with_negatives: (&[-7, -3, -2, 5, 8], -4, true), |
| 52 | + test_negative_sum_with_negatives_no_solution: (&[-7, -3, -2, 5, 8], -14, false), |
| 53 | + test_even_inputs_odd_target: (&[2, 4, 6, 2, 8, -2, 10, 12, -24, 8, 12, 18], 3, false), |
| 54 | + } |
| 55 | +} |
0 commit comments