Skip to content

Commit

Permalink
add m2m to main.rs and add docstring and readme
Browse files Browse the repository at this point in the history
  • Loading branch information
europeanplaice committed Feb 15, 2022
1 parent fb1e589 commit 45660d4
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "subset_sum"
version = "0.7.0"
version = "0.8.0"
edition = "2018"
authors = ["Tomohiro Endo <[email protected]>"]
description = "Solves subset sum problem and return a set of decomposed integers."
Expand Down
10 changes: 5 additions & 5 deletions key.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
1000
1100
150
123
5
1980
2980
3500
4000
1050
75 changes: 72 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
```
Expand Down Expand Up @@ -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`
Expand All @@ -66,7 +109,7 @@ subset_sum = "(version)"
```
Example
```
subset_sum = "0.7.0"
subset_sum = "0.8.0"
```

### Subset sum
Expand All @@ -83,7 +126,7 @@ Output
```
[[-8, -10]]
```
### Sequence Matcher
### Sequence Matcher (One-to-Many)
`main.rs`
```rust
use subset_sum::dp::sequence_matcher;
Expand All @@ -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])]
```
58 changes: 46 additions & 12 deletions src/dp_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<i32>,
targets: &mut Vec<i32>,
n_max: usize
Expand All @@ -306,15 +340,15 @@ pub mod dp {
let mut answer: Vec<Vec<(VecDeque<i32>, VecDeque<i32>)>> = 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();
answer.dedup();
answer
}

fn sequence_matcher_core_n2n(key: &mut Vec<i32>, targets: &mut Vec<i32>,
fn sequence_matcher_core_m2m(key: &mut Vec<i32>, targets: &mut Vec<i32>,
group: &mut Vec<(VecDeque<i32>, VecDeque<i32>)>,
answer: &mut Vec<Vec<(VecDeque<i32>, VecDeque<i32>)>>,
n_key: usize, len_key: usize, key_orig: &mut Vec<i32>,
Expand All @@ -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;
}

Expand All @@ -353,7 +387,7 @@ pub mod dp {
}
let set_: Vec<VecDeque<i32>> = 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());
Expand All @@ -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);
Expand Down Expand Up @@ -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])),
Expand Down
14 changes: 11 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ fn main() {
for line in line2{
targets.push(line.unwrap().trim().parse::<i32>().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<i32> = Vec::new();
Expand Down
13 changes: 8 additions & 5 deletions targets.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
1900
1950
2900
30
80
3300
200
151
4
100
23
3980
1050
20

0 comments on commit 45660d4

Please sign in to comment.