diff --git a/tig-algorithms/src/knapsack/dynamic.rs b/tig-algorithms/src/knapsack/dynamic.rs new file mode 100644 index 00000000..f84ff0a9 --- /dev/null +++ b/tig-algorithms/src/knapsack/dynamic.rs @@ -0,0 +1,58 @@ +use tig_challenges::knapsack::*; + +pub fn solve_challenge(challenge: &Challenge) -> anyhow::Result> { + let max_weight = challenge.max_weight; + let min_value = challenge.min_value; + let num_items = challenge.difficulty.num_items; + + // Sort items by value-to-weight ratio in descending order + let mut sorted_items: Vec = (0..num_items).collect(); + sorted_items.sort_by(|&a, &b| { + let ratio_a = challenge.values[a] as f64 / challenge.weights[a] as f64; + let ratio_b = challenge.values[b] as f64 / challenge.weights[b] as f64; + ratio_b.partial_cmp(&ratio_a).unwrap() + }); + + // Initialize combinations with a single empty combo + let mut combinations: Vec<(Vec, u32, u32)> = vec![(vec![false; num_items], 0, 0)]; + + let mut items = Vec::new(); + for &item in &sorted_items { + // Create new combos with the current item + let mut new_combinations: Vec<(Vec, u32, u32)> = combinations + .iter() + .map(|(combo, value, weight)| { + let mut new_combo = combo.clone(); + new_combo[item] = true; + ( + new_combo, + value + challenge.values[item], + weight + challenge.weights[item], + ) + }) + .filter(|&(_, _, weight)| weight <= max_weight) // Keep only combos within weight limit + .collect(); + + // Check if any new combination meets the minimum value requirement + if let Some((combo, _, _)) = new_combinations + .iter() + .find(|&&(_, value, _)| value >= min_value) + { + items = combo + .iter() + .enumerate() + .filter_map(|(i, &included)| if included { Some(i) } else { None }) + .collect(); + break; + } + + // Merge new_combinations with existing combinations + combinations.append(&mut new_combinations); + + // Deduplicate combinations by keeping the highest value for each weight + combinations.sort_by(|a, b| a.2.cmp(&b.2).then_with(|| b.1.cmp(&a.1))); // Sort by weight, then by value + combinations.dedup_by(|a, b| a.2 == b.2 && a.1 <= b.1); // Deduplicate by weight, keeping highest value + } + + Ok(Some(Solution { items })) +} diff --git a/tig-algorithms/src/knapsack/mod.rs b/tig-algorithms/src/knapsack/mod.rs index a6baab13..0d4c6407 100644 --- a/tig-algorithms/src/knapsack/mod.rs +++ b/tig-algorithms/src/knapsack/mod.rs @@ -1,4 +1,4 @@ -// c003_a001 placeholder +pub mod dynamic; // c003_a002 placeholder // c003_a003 placeholder // c003_a004 placeholder diff --git a/tig-algorithms/wasm/knapsack/dynamic.wasm b/tig-algorithms/wasm/knapsack/dynamic.wasm new file mode 100644 index 00000000..c6bb3568 Binary files /dev/null and b/tig-algorithms/wasm/knapsack/dynamic.wasm differ