This is a Rust implementation that calculates subset sum problem using dynamic programming. It 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.
Any feedback is welcome!
There are four ways to use this program. * CLI🖥️ * Rust🦀 * Python🐍 * Web🌎 (Easy to use)
Here is also an out of the box example of python you can run now in google colab. https://colab.research.google.com/github/europeanplaice/subsetsum/blob/main/python/pythonsubset_sum.ipynb
And it has two methods.
find_subset
Sequence Matcher
dpss
is short for dynamic programming subset sum
.
|Name|URL| |--|--| |github|https://github.com/europeanplaice/subsetsum| |crates.io|https://crates.io/crates/subsetsum| |docs.rs|https://docs.rs/subsetsum/latest/dpss/| |pypi|https://pypi.org/project/dpss/| |Website|https://europeanplaice.github.io/subsetsum/|
Binary files are provided on the Releases page. When you download one of these, please add it to your PATH manually.
First, you need to prepare a text file containing a set of integers like this
1
2
-3
4
5
and save it at any place.
Second, call subset_sum
with the path of the text file and the target sum.
Call subset_sum.exe num_set.txt 3 3
The executable's name subset_sum.exe
would be different from your choice. Change this example along with your environment.
The second argument is the target sum.
The third argument is the maximum length of the combination.
In this example, the output is
[[2, 1], [4, -3, 2], [5, -3, 1]]
arr1.txt
1980
2980
3500
4000
1050
arr2.txt
1950
2900
30
80
3300
200
3980
1050
20
Call subset_sum.exe arr1.txt arr2.txt 100 100 10
In this example, the output is
```
pattern 1 => [((1050) -> [1050] == [1050])
((12460) -> [1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1950 + 2900 + 3300 + 3980])],
pattern 2 => [((13510) -> [1050 + 1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1050 + 1950 + 2900 + 3300 + 3980])],
pattern 3 => [((1980) -> [1980] == [30 + 1950]) ((11530) -> [1050 + 2980 + 3500 + 4000] == [20 + 80 + 200 + 1050 + 2900 + 3300 + 3980])],
pattern 4 => [((2980) -> [2980] == [80 + 2900]) ((10530) -> [1050 + 1980 + 3500 + 4000] == [20 + 30 + 200 + 1050 + 1950 + 3300 + 3980])],
pattern 5 => [((2980) -> [2980] == [80 + 2900]) ((4000) -> [4000] == [20 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 6 => [((6980) -> [2980 + 4000] == [20 + 80 + 2900 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 7 => [((3500) -> [3500] == [200 + 3300]) ((10010) -> [1050 + 1980 + 2980 + 4000] == [20 + 30 + 80 + 1050 + 1950 + 2900 + 3980])],
pattern 8 => [((7500) -> [3500 + 4000] == [20 + 30 + 200 + 1050 + 2900 + 3300]) ((6010) -> [1050 + 1980 + 2980] == [80 + 1950 + 3980])],
pattern 9 => [((4000) -> [4000] == [20 + 30 + 1050 + 2900]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [80 + 200 + 1950 + 3300 + 3980])],
pattern 10 => [((4000) -> [4000] == [20 + 3980]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [30 + 80 + 200 + 1050 + 1950 + 2900 + 3300])], ```
pip install dpss
find_subset
python
import inspect
import dpss
help(dpss.find_subset)
```
findsubset(arr, value, maxlength, /) Finds subsets sum of a target value. It can accept negative values. # Arguments *
arr
- An array. *value
- The value to the sum of the subset comes. *max_length
- The maximum length of combinations of the answer. ```
python
print(dpss.find_subset([1, -2, 3, 4, 5], 2, 3))
```
[[4, -2], [3, -2, 1]] ```
sequence_matcher
python
help(dpss.sequence_matcher)
```
sequencematcher(keys, targets, maxkeylength, maxtargetlength /) 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
keys
vector corresponds to the multiple integers of thetargets
vector. With this method, we can find some combinations of the integers. # Arguments *keys
- An array. *targets
- An array. *max_key_length
- An integer. *max_target_length
- An integer. *n_candidates
- An integer.python a = dpss.sequencematcher( [1980, 2980, 3500, 4000, 1050], [1950, 2900, 30, 80, 3300, 200, 3980, 1050, 20], 10, 10, 10) print(dpss.sequencematcherformatter(a))
pattern 1 => [((1050) -> [1050] == [1050]) ((12460) -> [1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1950 + 2900 + 3300 + 3980])],
pattern 2 => [((13510) -> [1050 + 1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1050 + 1950 + 2900 + 3300 + 3980])],
pattern 3 => [((1980) -> [1980] == [30 + 1950]) ((11530) -> [1050 + 2980 + 3500 + 4000] == [20 + 80 + 200 + 1050 + 2900 + 3300 + 3980])],
pattern 4 => [((2980) -> [2980] == [80 + 2900]) ((10530) -> [1050 + 1980 + 3500 + 4000] == [20 + 30 + 200 + 1050 + 1950 + 3300 + 3980])],
pattern 5 => [((2980) -> [2980] == [80 + 2900]) ((4000) -> [4000] == [20 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 6 => [((6980) -> [2980 + 4000] == [20 + 80 + 2900 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 7 => [((3500) -> [3500] == [200 + 3300]) ((10010) -> [1050 + 1980 + 2980 + 4000] == [20 + 30 + 80 + 1050 + 1950 + 2900 + 3980])],
pattern 8 => [((7500) -> [3500 + 4000] == [20 + 30 + 200 + 1050 + 2900 + 3300]) ((6010) -> [1050 + 1980 + 2980] == [80 + 1950 + 3980])],
pattern 9 => [((4000) -> [4000] == [20 + 30 + 1050 + 2900]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [80 + 200 + 1950 + 3300 + 3980])],
pattern 10 => [((4000) -> [4000] == [20 + 3980]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [30 + 80 + 200 + 1050 + 1950 + 2900 + 3300])], ```
Please check https://crates.io/crates/subset_sum.
Cargo.toml
[dependencies]
dpss = { version = "(version)", package = "subset_sum" }
main.rs
```rust
use dpss::dp::find_subset;
fn main() {
let result = find_subset(&mut vec![1, 2, 3, 4, 5], 6, 3);
println!("{:?}", result);
}
Output
[[3, 2, 1], [4, 2], [5, 1]]
```
main.rs
```rust
use dpss::dp::sequencematcher;
use dpss::dp::sequencematcher_formatter;
fn main() {
let result = sequencematcher(&mut vec![1980, 2980, 3500, 4000, 1050], &mut vec![1950, 2900, 30, 80, 3300, 200, 3980, 1050, 20], 10, 10, 10);
println!("{}", sequencematcher_formatter(result));
}
Output
pattern 1 => [((1050) -> [1050] == [1050])
((12460) -> [1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1950 + 2900 + 3300 + 3980])],
pattern 2 => [((13510) -> [1050 + 1980 + 2980 + 3500 + 4000] == [20 + 30 + 80 + 200 + 1050 + 1950 + 2900 + 3300 + 3980])],
pattern 3 => [((1980) -> [1980] == [30 + 1950]) ((11530) -> [1050 + 2980 + 3500 + 4000] == [20 + 80 + 200 + 1050 + 2900 + 3300 + 3980])],
pattern 4 => [((2980) -> [2980] == [80 + 2900]) ((10530) -> [1050 + 1980 + 3500 + 4000] == [20 + 30 + 200 + 1050 + 1950 + 3300 + 3980])],
pattern 5 => [((2980) -> [2980] == [80 + 2900]) ((4000) -> [4000] == [20 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 6 => [((6980) -> [2980 + 4000] == [20 + 80 + 2900 + 3980]) ((6530) -> [1050 + 1980 + 3500] == [30 + 200 + 1050 + 1950 + 3300])],
pattern 7 => [((3500) -> [3500] == [200 + 3300]) ((10010) -> [1050 + 1980 + 2980 + 4000] == [20 + 30 + 80 + 1050 + 1950 + 2900 + 3980])],
pattern 8 => [((7500) -> [3500 + 4000] == [20 + 30 + 200 + 1050 + 2900 + 3300]) ((6010) -> [1050 + 1980 + 2980] == [80 + 1950 + 3980])],
pattern 9 => [((4000) -> [4000] == [20 + 30 + 1050 + 2900]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [80 + 200 + 1950 + 3300 + 3980])],
pattern 10 => [((4000) -> [4000] == [20 + 3980]) ((9510) -> [1050 + 1980 + 2980 + 3500] == [30 + 80 + 200 + 1050 + 1950 + 2900 + 3300])], ... ```