From 45660d4ecc9c8efae4e1cb77464cedb035bf55c2 Mon Sep 17 00:00:00 2001 From: europeanplaice Date: Wed, 16 Feb 2022 06:50:47 +0900 Subject: [PATCH] add m2m to main.rs and add docstring and readme --- Cargo.lock | 2 +- Cargo.toml | 2 +- key.txt | 10 +++---- readme.md | 75 ++++++++++++++++++++++++++++++++++++++++++++++-- src/dp_module.rs | 58 +++++++++++++++++++++++++++++-------- src/main.rs | 14 +++++++-- targets.txt | 13 +++++---- 7 files changed, 144 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f806d3a..1301aac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,7 +498,7 @@ dependencies = [ [[package]] name = "subset_sum" -version = "0.7.0" +version = "0.8.0" dependencies = [ "criterion", "rand", diff --git a/Cargo.toml b/Cargo.toml index ec36557..2812308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "subset_sum" -version = "0.7.0" +version = "0.8.0" edition = "2018" authors = ["Tomohiro Endo "] description = "Solves subset sum problem and return a set of decomposed integers." diff --git a/key.txt b/key.txt index 247a4ec..b664f55 100644 --- a/key.txt +++ b/key.txt @@ -1,5 +1,5 @@ -1000 -1100 -150 -123 -5 \ No newline at end of file +1980 +2980 +3500 +4000 +1050 \ No newline at end of file diff --git a/readme.md b/readme.md index 7c9a5b0..297cdf4 100644 --- a/readme.md +++ b/readme.md @@ -29,7 +29,7 @@ The executable's name `subset_sum.exe` would be different from your choice. Chan In this example, the output is `[[1, 2], [2, -3, 4], [1, -3, 5]]` -### Sequence Matcher +### Sequence Matcher (One-to-Many) `key.txt` ``` @@ -57,6 +57,49 @@ In this example, the output is [([1, -3, 5], 3), ([5], 5), ([4, 3], 7)] ``` +### Sequence Matcher (Many-to-Many) + +`key.txt` +``` +1980 +2980 +3500 +4000 +1050 +``` + +`targets.txt` +``` +1950 +2900 +30 +80 +3300 +200 +3980 +1050 +20 +``` + +Call `subset_sum.exe key.txt targets.txt m2m` + +In this example, the output is +``` +[([20, 30, 1050, 2900], [4000]), ([80, 1950, 3980], [1050, 1980, 2980]), ([200, 3300], [3500])] +[([20, 30, 1050, 2900], [4000]), ([200, 3300], [3500]), ([80, 1950, 3980], [1050, 1980, 2980])] +[([20, 3980], [4000]), ([80, 2900], [2980]), ([30, 1950], [1980]), ([1050], [1050]), ([200, 3300], [3500])] +[([20, 3980], [4000]), ([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980]), ([200, 3300], [3500])] +[([20, 3980], [4000]), ([200, 3300], [3500]), ([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([20, 3980], [4000]), ([200, 3300], [3500]), ([1050], [1050])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([200, 3300], [3500]), ([20, 3980], [4000]), ([1050], [1050])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([1050], [1050]), ([20, 3980], [4000]), ([200, 3300], [3500])] +[([80, 2900], [2980]), ([20, 3980], [4000]), ([1050], [1050]), ([200, 3300], [3500]), ([30, 1950], [1980])] +[([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980]), ([20, 3980], [4000]), ([200, 3300], [3500])] +[([200, 3300], [3500]), ([20, 30, 1050, 2900], [4000]), ([80, 1950, 3980], [1050, 1980, 2980])] +[([200, 3300], [3500]), ([20, 3980], [4000]), ([80, 2900], [2980]), ([30, 1950], [1980]), ([1050], [1050])] +[([1050], [1050]), ([30, 1950], [1980]), ([20, 3980], [4000]), ([80, 2900], [2980]), ([200, 3300], [3500])] +``` +There are a lot of combinations! ## Use in Rust `Cargo.toml` @@ -66,7 +109,7 @@ subset_sum = "(version)" ``` Example ``` -subset_sum = "0.7.0" +subset_sum = "0.8.0" ``` ### Subset sum @@ -83,7 +126,7 @@ Output ``` [[-8, -10]] ``` -### Sequence Matcher +### Sequence Matcher (One-to-Many) `main.rs` ```rust use subset_sum::dp::sequence_matcher; @@ -101,3 +144,29 @@ Output [([1, -3, 5], 3), ([5], 5), ([4, 3], 7)] ] ``` +### Sequence Matcher (Many-to-Many) +`main.rs` +```rust +use subset_sum::dp::sequence_matcher_m2m; + +fn main() { + let result = sequence_matcher_m2m(&mut vec![1980, 2980, 3500, 4000, 1050], &mut vec![1950, 2900, 30, 80, 3300, 200, 3980, 1050, 20], 10); + println!("{:?}", result); +} +``` +Output +``` +[([20, 30, 1050, 2900], [4000]), ([80, 1950, 3980], [1050, 1980, 2980]), ([200, 3300], [3500])] +[([20, 30, 1050, 2900], [4000]), ([200, 3300], [3500]), ([80, 1950, 3980], [1050, 1980, 2980])] +[([20, 3980], [4000]), ([80, 2900], [2980]), ([30, 1950], [1980]), ([1050], [1050]), ([200, 3300], [3500])] +[([20, 3980], [4000]), ([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980]), ([200, 3300], [3500])] +[([20, 3980], [4000]), ([200, 3300], [3500]), ([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([20, 3980], [4000]), ([200, 3300], [3500]), ([1050], [1050])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([200, 3300], [3500]), ([20, 3980], [4000]), ([1050], [1050])] +[([30, 1950], [1980]), ([80, 2900], [2980]), ([1050], [1050]), ([20, 3980], [4000]), ([200, 3300], [3500])] +[([80, 2900], [2980]), ([20, 3980], [4000]), ([1050], [1050]), ([200, 3300], [3500]), ([30, 1950], [1980])] +[([80, 2900], [2980]), ([1050], [1050]), ([30, 1950], [1980]), ([20, 3980], [4000]), ([200, 3300], [3500])] +[([200, 3300], [3500]), ([20, 30, 1050, 2900], [4000]), ([80, 1950, 3980], [1050, 1980, 2980])] +[([200, 3300], [3500]), ([20, 3980], [4000]), ([80, 2900], [2980]), ([30, 1950], [1980]), ([1050], [1050])] +[([1050], [1050]), ([30, 1950], [1980]), ([20, 3980], [4000]), ([80, 2900], [2980]), ([200, 3300], [3500])] +``` diff --git a/src/dp_module.rs b/src/dp_module.rs index 3f99f2b..c77a3af 100644 --- a/src/dp_module.rs +++ b/src/dp_module.rs @@ -224,7 +224,9 @@ pub mod dp { a.remove(index); } - /// Finds the intergers from two vectors that sum to the same value. + /// Finds the integers from two vectors that sum to the same value. + /// This method assumes that the two vectors have One-to-Many relationships. + /// Each integer of the `key` vector corresponds to the multiple integers of the `value` vector. /// # Example /// ``` /// use std::collections::VecDeque; @@ -292,8 +294,40 @@ pub mod dp { } } - - pub fn sequence_matcher_n2n( + /// Finds the integers from two vectors that sum to the same value. + /// This method assumes that the two vectors have Many-to-Many relationships. + /// Each integer of the `key` vector corresponds to the multiple integers of the `value` vector. + /// With this method, we can find multiple combinations of the integers. + /// # Example + /// + /// ```rust + ///use std::collections::VecDeque; + ///use subset_sum::dp::sequence_matcher_m2m; + ///let answer = sequence_matcher_m2m(&mut vec![1980, 2980, 3500, 4000, 1050], &mut vec![1950, 2900, 30, 80, 3300, 200, 3980, 1050, 20], 10); + ///assert_eq!(answer[0], vec![ + /// (VecDeque::from(vec![20, 30, 1050, 2900]), + /// VecDeque::from(vec![4000])), + /// + /// (VecDeque::from(vec![80, 1950, 3980]), + /// VecDeque::from(vec![1050, 1980, 2980])), + /// + /// (VecDeque::from(vec![200, 3300]), + /// VecDeque::from(vec![3500])), + /// + /// ]); + ///assert_eq!(answer[1], vec![ + /// (VecDeque::from(vec![20, 30, 1050, 2900]), + /// VecDeque::from(vec![4000])), + /// + /// (VecDeque::from(vec![200, 3300]), + /// VecDeque::from(vec![3500])), + /// + /// (VecDeque::from(vec![80, 1950, 3980]), + /// VecDeque::from(vec![1050, 1980, 2980])), + /// + /// ]); + /// ``` + pub fn sequence_matcher_m2m( key: &mut Vec, targets: &mut Vec, n_max: usize @@ -306,7 +340,7 @@ pub mod dp { let mut answer: Vec, VecDeque)>> = Vec::new(); let mut rng: rand::rngs::StdRng = rand::SeedableRng::from_seed([13; 32]); for i in 0..n_max { - sequence_matcher_core_n2n(key, targets, &mut group, &mut answer, 1, key.len(), &mut key.clone(), rng.clone()); + sequence_matcher_core_m2m(key, targets, &mut group, &mut answer, 1, key.len(), &mut key.clone(), rng.clone()); key.shuffle(&mut rng); } answer.sort(); @@ -314,7 +348,7 @@ pub mod dp { answer } - fn sequence_matcher_core_n2n(key: &mut Vec, targets: &mut Vec, + fn sequence_matcher_core_m2m(key: &mut Vec, targets: &mut Vec, group: &mut Vec<(VecDeque, VecDeque)>, answer: &mut Vec, VecDeque)>>, n_key: usize, len_key: usize, key_orig: &mut Vec, @@ -334,13 +368,13 @@ pub mod dp { return; } if (key.len() == 0 && targets.len() > 0) || (key.len() > 0 && targets.len() == 0) { - sequence_matcher_core_n2n(key, targets, group, answer, n_key+1, len_key, key_orig, rng.clone()); + sequence_matcher_core_m2m(key, targets, group, answer, n_key+1, len_key, key_orig, rng.clone()); } if n_key > key.len(){ let mut new_key = key.clone(); new_key.shuffle(&mut rng); - sequence_matcher_core_n2n(&mut new_key, targets, group, answer, 1, len_key, key_orig, rng.clone()); + sequence_matcher_core_m2m(&mut new_key, targets, group, answer, 1, len_key, key_orig, rng.clone()); return; } @@ -353,7 +387,7 @@ pub mod dp { } let set_: Vec> = find_subset(&targets, sum_key); if set_.len() == 0 { - sequence_matcher_core_n2n(key, targets, group, answer, n_key+1, len_key, key_orig, rng.clone()); + sequence_matcher_core_m2m(key, targets, group, answer, n_key+1, len_key, key_orig, rng.clone()); } for set in set_ { let mut _set = Vec::from(set.clone()); @@ -367,7 +401,7 @@ pub mod dp { for i in vec_key.clone(){ vec_remove(key, i); } - sequence_matcher_core_n2n(key, targets, group, answer, n_key, len_key, key_orig, rng.clone()); + sequence_matcher_core_m2m(key, targets, group, answer, n_key, len_key, key_orig, rng.clone()); group.pop(); for el in set.clone(){ targets.push(el); @@ -420,14 +454,14 @@ pub mod dp { } #[test] - fn test_sequence_matcher_n2n(){ + fn test_sequence_matcher_m2m(){ - let answer = sequence_matcher_n2n(&mut vec![1, 2, 3, 4, 5], &mut vec![11, -8, 14, -7, 5], 10); + let answer = sequence_matcher_m2m(&mut vec![1, 2, 3, 4, 5], &mut vec![11, -8, 14, -7, 5], 10); assert_eq!(answer[0], vec![ (VecDeque::from(vec![-8, -7, 5, 11]), VecDeque::from(vec![1])), (VecDeque::from(vec![14]), VecDeque::from(vec![2, 3, 4, 5])), ]); - let answer = sequence_matcher_n2n(&mut vec![1000, 1100, 150, 123, 5, 10], &mut vec![2100, 273, 4, 11], 10); + let answer = sequence_matcher_m2m(&mut vec![1000, 1100, 150, 123, 5, 10], &mut vec![2100, 273, 4, 11], 10); assert_eq!(answer[0], vec![ (VecDeque::from(vec![4, 11]), VecDeque::from(vec![5, 10])), diff --git a/src/main.rs b/src/main.rs index 7d09d07..9206254 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,9 +21,17 @@ fn main() { for line in line2{ targets.push(line.unwrap().trim().parse::().unwrap()); } - let result = dp_module::dp::sequence_matcher_n2n(&mut key, &mut targets, 10); - for elem in result{ - println!("{:?}", elem); + if args.len() == 4 && args[3] == "m2m"{ + let result = dp_module::dp::sequence_matcher_m2m(&mut key, &mut targets, 10); + for elem in result{ + println!("{:?}", elem); + } + } else { + let result = dp_module::dp::sequence_matcher(&mut key, &mut targets); + for elem in result{ + println!("{:?}", elem); + } + } } else { let mut a: Vec = Vec::new(); diff --git a/targets.txt b/targets.txt index 44b62ac..71b9bb5 100644 --- a/targets.txt +++ b/targets.txt @@ -1,6 +1,9 @@ -1900 +1950 +2900 +30 +80 +3300 200 -151 -4 -100 -23 \ No newline at end of file +3980 +1050 +20 \ No newline at end of file