Skip to content

Commit

Permalink
Skip unnecessary loop in find_subset
Browse files Browse the repository at this point in the history
  • Loading branch information
europeanplaice committed Feb 22, 2022
1 parent 2e7a0c6 commit d583456
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 59 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.10.5"
version = "0.11.0"
edition = "2018"
authors = ["Tomohiro Endo <europeanplaice@gmail.com>"]
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."
Expand Down
6 changes: 1 addition & 5 deletions key.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
1980
2980
3500
4000
1050
4
11 changes: 1 addition & 10 deletions num_set.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
1
2
3
4
5
6
7
-8
9
-10
5
2 changes: 1 addition & 1 deletion python/test_py_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


def test_find_subset():
assert dpss.find_subset([1, 2, 3, 4, 5], 6) == [[4, 2], [5, 1], [3, 2, 1]]
assert dpss.find_subset([1, 2, 3, 4, 5], 6) == [[3, 2, 1], [4, 2], [5, 1]]


def test_find_subset_fast_only_positive():
Expand Down
85 changes: 53 additions & 32 deletions src/dp_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,32 +54,47 @@ pub mod dp {
use std::cmp::min;
// https://stackoverflow.com/questions/43078142/subset-sum-with-negative-values-in-c-or-c
// Find a subset even if an array contains negative values.
let offset: u32 = (max(a.iter().min().unwrap().abs() + 1, min(n, 0).abs() + 1)) as u32;
let mut b: Vec<u32> = Vec::new();
for i in a {
b.push((i + offset as i32) as u32);
}
let mut answer: Vec<Vec<i32>> = Vec::new();

// We will transform the array into a new array whose elements are all positive.
// And check if the transformed sum of the result of the new array is equal to the target value.
// If we find the sum is the same as the target, we will return the result.
for i in 1..a.len() + 1 {
let result =
find_subset_fast_only_positive(&b, (n + i as i32 * offset as i32) as usize);
for res in result {
let mut tempsum: i32 = 0;
let mut new_res: Vec<i32> = Vec::new();
for el in res {
tempsum += el as i32 - offset as i32;
new_res.push(el as i32 - offset as i32);
let mut b: Vec<u32> = Vec::with_capacity(a.len());
let mut answer: Vec<Vec<i32>> = Vec::with_capacity(a.len());
if a.iter().min().unwrap() > &0 && n > 0 {
for i in a {
b.push(*i as u32);
}
let result = find_subset_fast_only_positive(&b, n as usize);
for i in result {
let mut tempvec = Vec::with_capacity(i.len());
for j in i {
tempvec.push(j as i32);
}
if tempsum == n as i32 {
answer.push(new_res);
answer.push(tempvec)
}
return answer;
} else {
let offset: u32 = (max(a.iter().min().unwrap().abs() + 1, min(n, 0).abs() + 1)) as u32;
for i in a {
b.push((i + offset as i32) as u32);
}

// We will transform the array into a new array whose elements are all positive.
// And check if the transformed sum of the result of the new array is equal to the target value.
// If we find the sum is the same as the target, we will return the result.
for i in 1..a.len() + 1 {
let result =
find_subset_fast_only_positive(&b, (n + i as i32 * offset as i32) as usize);
for res in result {
let mut tempsum: i32 = 0;
let mut new_res: Vec<i32> = Vec::new();
for el in res {
tempsum += el as i32 - offset as i32;
new_res.push(el as i32 - offset as i32);
}
if tempsum == n as i32 {
answer.push(new_res);
}
}
}
}
answer
return answer;
};
}

fn rec(
Expand Down Expand Up @@ -209,8 +224,8 @@ pub mod dp {
}
}
let a_length: usize = a.len();
let mut route: Vec<u32> = Vec::new();
let mut answer: Vec<Vec<u32>> = Vec::new();
let mut route: Vec<u32> = Vec::with_capacity(a_length);
let mut answer: Vec<Vec<u32>> = Vec::with_capacity(a_length);

rec(&dp, &a, a_length, n, &mut route, &mut answer, &a_min);
answer
Expand Down Expand Up @@ -258,6 +273,9 @@ pub mod dp {
let mut group: Vec<(Vec<i32>, i32)> = Vec::new();
let mut answer: Vec<Vec<(Vec<i32>, i32)>> = Vec::new();
sequence_matcher_core(key, targets, &mut group, &mut answer);
if answer.len() == 0 {
println!("Can't find any combination.");
}
answer
}

Expand Down Expand Up @@ -344,7 +362,7 @@ pub mod dp {
use rand::seq::SliceRandom;

let mut group: Vec<(Vec<i32>, Vec<i32>)> = Vec::new();
let mut answer: Vec<Vec<(Vec<i32>, Vec<i32>)>> = Vec::new();
let mut answer: Vec<Vec<(Vec<i32>, Vec<i32>)>> = Vec::with_capacity(n_max);
let mut rng: rand::rngs::StdRng = rand::SeedableRng::from_seed([13; 32]);
if key.iter().sum::<i32>() != targets.iter().sum() {
println!("The sum of the key must be equal to the sum of the targets.");
Expand All @@ -356,6 +374,9 @@ pub mod dp {
}
answer.sort();
answer.dedup();
if answer.len() == 0 {
println!("Can't find any combination.");
}
answer
}

Expand Down Expand Up @@ -525,17 +546,17 @@ mod tests {
}

#[test]
fn test_find_test() {
fn test_find_subset() {
let result = dp::find_subset(&vec![1, 2, 3], 3);
let route1: Vec<i32> = vec![3];
let route2: Vec<i32> = vec![2, 1];
let route1: Vec<i32> = vec![2, 1];
let route2: Vec<i32> = vec![3];
let answer: Vec<Vec<i32>> = vec![route1, route2];
assert_eq!(result, answer);

let result = dp::find_subset(&vec![1, 2, 3, 4, 5], 10);
let route1: Vec<i32> = vec![5, 3, 2];
let route2: Vec<i32> = vec![5, 4, 1];
let route3: Vec<i32> = vec![4, 3, 2, 1];
let route1: Vec<i32> = vec![4, 3, 2, 1];
let route2: Vec<i32> = vec![5, 3, 2];
let route3: Vec<i32> = vec![5, 4, 1];
let answer: Vec<Vec<i32>> = vec![route1, route2, route3];
assert_eq!(result, answer);

Expand Down
11 changes: 2 additions & 9 deletions targets.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,2 @@
1950
2900
30
80
3300
200
3980
1050
20
2
3

0 comments on commit d583456

Please sign in to comment.