diff --git a/Cargo.lock b/Cargo.lock index 186f47e..017d461 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -318,7 +318,7 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" [[package]] name = "subset_sum" -version = "0.18.1" +version = "0.18.2" dependencies = [ "itertools", "pyo3", diff --git a/Cargo.toml b/Cargo.toml index 7dd069c..2ef9310 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "subset_sum" -version = "0.18.1" +version = "0.18.2" edition = "2018" authors = ["Tomohiro Endo "] description = "Solves subset sum problem and returns a set of decomposed integers. It also can match corresponding numbers from two vectors and be used for Account reconciliation." diff --git a/docs/pkg/dpss_bg.wasm b/docs/pkg/dpss_bg.wasm index 86f3eca..d20acad 100644 Binary files a/docs/pkg/dpss_bg.wasm and b/docs/pkg/dpss_bg.wasm differ diff --git a/docs/pkg/package.json b/docs/pkg/package.json index 2140dbd..084300b 100644 --- a/docs/pkg/package.json +++ b/docs/pkg/package.json @@ -4,7 +4,7 @@ "Tomohiro Endo " ], "description": "Solves subset sum problem and returns a set of decomposed integers. It also can match corresponding numbers from two vectors and be used for Account reconciliation.", - "version": "0.18.1", + "version": "0.18.2", "license": "MIT", "repository": { "type": "git", diff --git a/readme.md b/readme.md index f60f2bd..38573a3 100644 --- a/readme.md +++ b/readme.md @@ -39,6 +39,7 @@ And it has three methods. |crates.io|https://crates.io/crates/subset_sum| |docs.rs|https://docs.rs/subset_sum/latest/dpss/| |pypi|https://pypi.org/project/dpss/| +|Website|https://europeanplaice.github.io/subset_sum/| ## CLI diff --git a/src/dp_module.rs b/src/dp_module.rs index 6a10914..6ccf07d 100644 --- a/src/dp_module.rs +++ b/src/dp_module.rs @@ -100,14 +100,15 @@ pub mod dp { } fn rec( - dp: &Vec, + dp: &Vec, arr: &Vec, i: usize, j: usize, route: &mut Vec, answer: &mut Vec>, max_length: usize, - collen: usize + collen: usize, + last_value: usize ) { // This code is mostly copied from https://drken1215.hatenablog.com/entry/2019/12/17/190300 // We follow the dp table backward to find combinations of subsets. @@ -122,30 +123,35 @@ pub mod dp { return; } - if answer.len() > dp[dp.len() - 1] as usize { + if answer.len() > last_value { return; } if route.len() > max_length { return; } + let i_minus_one = i - 1; + let one_step_up = i_minus_one * collen + j; + let v = arr[i_minus_one]; - if dp[(i - 1) * collen + j] != 0 { - rec(dp, arr, i - 1, j, route, answer, max_length, collen); + if dp[one_step_up] != 0 { + rec(dp, arr, i_minus_one, j, route, answer, max_length, collen, last_value); } - if j as i32 - arr[i - 1] as i32 >= 0 && dp[(i - 1) * collen + j - arr[i - 1] as usize] != 0 { + let j_v = j as i32 - v as i32; + if j_v >= 0 && dp[one_step_up - v as usize] != 0 { // Choose this element as arr candidate for an answer. - route.push(arr[i - 1]); + route.push(v); rec( dp, arr, - i - 1, - j - arr[i - 1] as usize, + i_minus_one, + j_v as usize, route, answer, max_length, - collen + collen, + last_value ); // Remove this element after we reach i == 0 regardless of whether we reach j == 0. route.pop(); @@ -226,34 +232,38 @@ pub mod dp { // We follow from the start of this table. // let mut dp: Vec> = vec![vec![0; value + 1]; arr.len() + 1]; let collen = value + 1; - let mut dp: Vec = vec![0; (value + 1) * (arr.len() + 1)]; + let mut dp: Vec = vec![0; (value + 1) * (arr.len() + 1)]; dp[0] = 1; - for (i, v_u32) in arr.iter().enumerate() { + let mut current_address= 0; + arr.iter().for_each(|v_u32| { let v_usize = *v_u32 as usize; - for j in 0..value+1 { + (0..value+1).for_each(|j| { + let current_value = dp[current_address]; + if current_value == 0 { + current_address += 1; + return; + }; + let address_onestep_down = current_address + collen; // If we don't choose to select an element to sum, // the ways to make a sum are the same as with the previous element. // dp[i + 1][*j] += dp[i][*j]; - if dp[i * collen + j] == 0 { - continue; - }; - dp[(i + 1) * collen + j] += dp[i * collen + j]; + dp[address_onestep_down] += current_value; // Skip if j + the element is larger than the target value. - if j + v_usize < value + 1 { + if j + v_usize < collen { // This means we find another way to make sum j with i elements // when we choose this element as an element to sum. // dp[i + 1][j + arr[i] as usize] += dp[i][j]; - dp[(i + 1) * collen + j + v_usize] += dp[i * collen + j]; + dp[address_onestep_down + v_usize] += current_value; } - }; - } + current_address += 1; + }); + }); let a_length: usize = arr.len(); let mut route: Vec = vec![]; let mut answer: Vec> = vec![]; - rec( &dp, &arr, @@ -262,7 +272,8 @@ pub mod dp { &mut route, &mut answer, max_length, - collen + collen, + dp[dp.len() - 1] as usize ); answer } @@ -397,10 +408,11 @@ pub mod dp { mc.for_each(|i| { let mut sum_key = 0; let mut vec_key = vec![]; - for j in i.iter() { - sum_key += keys[*j]; - vec_key.push(keys[*j].clone()); - } + i.iter().for_each(|j| { + let k = keys[*j]; + sum_key += k; + vec_key.push(k); + }); vec_key.sort(); if sum_key > targets.iter().sum() { return; @@ -427,12 +439,12 @@ pub mod dp { let mut targets3 = targets.clone(); let mut group3 = group.clone(); group3.push((vec_key.clone(), set.clone())); - for j in set.clone() { - vec_remove(&mut targets3, j); - } - for i in vec_key.clone() { - vec_remove(&mut keys3, i); - } + set.iter().for_each(|j| { + vec_remove(&mut targets3, *j); + }); + vec_key.iter().for_each(|i| { + vec_remove(&mut keys3, *i); + }); sequence_matcher_core( &mut keys3, &mut targets3, @@ -449,10 +461,11 @@ pub mod dp { mc.par_bridge().for_each(|i| { let mut sum_key = 0; let mut vec_key = vec![]; - for j in i.iter() { - sum_key += keys[*j]; - vec_key.push(keys[*j].clone()); - } + i.iter().for_each(|j| { + let k = keys[*j]; + sum_key += k; + vec_key.push(k); + }); vec_key.sort(); if sum_key > targets.iter().sum() { return; @@ -463,12 +476,12 @@ pub mod dp { if targets.iter().max().unwrap() == &0 { return; } - let mut set_ = match hashmap_fs.try_lock() { + let mut set_ = {match hashmap_fs.try_lock() { Ok(mut v) => {v.entry((targets.clone(), sum_key)) .or_insert(find_subset(targets.clone(), sum_key, max_target_length)) .clone()}, Err(_) => {find_subset(targets.clone(), sum_key, max_target_length)} - }; + }}; if set_.len() == 0 { return; } @@ -479,12 +492,12 @@ pub mod dp { let mut targets3 = targets.clone(); let mut group3 = group.clone(); group3.push((vec_key.clone(), set.clone())); - for j in set.clone() { - vec_remove(&mut targets3, j); - } - for i in vec_key.clone() { - vec_remove(&mut keys3, i); - } + set.iter().for_each(|j| { + vec_remove(&mut targets3, *j); + }); + vec_key.iter().for_each(|i| { + vec_remove(&mut keys3, *i); + }); sequence_matcher_core( &mut keys3, &mut targets3,