I have an array of components:
let components = ["a", "b", "c"];
It is possible to combine those components to make products; i.e., "a" + "b" = "ab"
.
I have a catalog of possible products:
let catalog = ["ab", "ac", "bc"];
Using something like lodash, we can create an array of possible products. Output array would look like ["ab", "ac", "bc"]
.
But the problem is that not all of those products could be built because once the component for one is used, it is no longer available for use in other products that require it.
I need an output that only shows possible outcomes. When there are only 3 components, and every catalog product requires 2, obviously it's not possible to create more than one product at a time. So an output that would express that each is either-or would look like [["ab"],["ac"],["bc"]]
. But if you have 4 components it is possible to create more than one product at a time.
let components = ["a", "b", "c", "d"];
Possible catalog products with these components should look like [["ad", "cb"], ["ac", "bd"], ["ab", "cd"]]
.
I need some help with the logic for a function that outputs an array like the above.
Below is an example of a function that outputs possible catalog products with the provided components. But it doesn't achieve the requirements stated above.
let components = ["a", "b", "c", "e"];
let catalog = [["a", "b"], ["a", "c"], ["b", "c"], ["c", "d"]];
// Check if subset is included in superset (respecting duplicates).
const isSubset = (subset, superset) => {
const subsetCount = _.countBy(subset)
const supersetCount = _.countBy(superset)
return _.every(subsetCount, (count, value) => supersetCount[value] >= count)
}
catalog.forEach(el => {
if (isSubset(catalog, components) == true) console.log(el)
});
// Filter all catalog items, that could be build by components
const matches = _.pickBy(catalog, (catalog, thing) => isSubset(catalog, components))
console.log(matches);
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.10/lodash.min.js"></script>
EDIT: The result should be an array of possible catalog products whose components do not overlap/conflict with other catalog products in their respective arrays. So for example, if we have...
let components = ["a", "b", "c", "d", "e"];
let catalog = ["ab", "ac", "ad", "ae", "bc", "bd", "be", "cd", "ce", "de"];
... the output should be something like:
// [ ["ab", "cd"], ["ab", "de"], ["ac", "bd"], ["ac", "be"], ["ad", "ce"], ["ad, "bc"], ["ae", "bc"], ["ae", "cd"] ]
It's possible I've missed some there, but the point is that the output should be an array that expresses the either-or relationship of its inner arrays. The products' combination order doesn't matter. For example, "cd" == "dc"
. No element in the inner arrays should share a component. For example, we should not have ["ab", "ac"]
.