Cartesian Product
The cartesian product is the complicated mathematical name for "every combination of multiple sets".
Basically, this is useful (to me) for modeling things like playing cards and dice probabilities.
You can see the code in action in this codepen.
function cartesian(setA, ...sets) {
let result = [];
for (const item of setA) {
result.push([item]);
}
if (sets.length > 0) {
for (const set of sets) {
result = set.flatMap(itemB =>
result.map(itemA => [...itemA, itemB])
);
}
}
return result;
}
// alternate typescript implementation:
function cartesianProduct<T>(...sets: T[][]) {
let result: T[][] = [[]];
sets.forEach((set) => {
result = set.flatMap((item) =>
result.map((current) => [...current, item])
);
});
return result;
}
// playing cards
log(
cartesian(
['A','2','3','4','5','6','7','8','9','T','J','Q','K'],
['H','D','C','S']
)
)
// 3d6 (crag dice game)
log(
cartesian(
['1','2','3','4','5','6'],
['1','2','3','4','5','6'],
['1','2','3','4','5','6'],
)
)
This is a simplified version:
function cartesian(...sets) {
let result = [[]];
for (const set of sets) {
result = set.flatMap(item =>
result.map(item2 => [...item2, item])
);
}
return result;
}
This is the single-line version by StackOverflow:
const cartesianProduct = (...sets) => {
return sets.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));
}
This is a version that uses recursion and generators (just for fun):
function* cartesian(...sets) {
if (sets.length > 1) {
const [set, ...rest] = sets;
for (const item of set) {
for (const item2 of cartesian(...rest)) {
yield [item, ...item2];
}
}
} else {
const set = sets[0];
for (const item of set) {
yield [item];
}
}
}
const cards = [...cartesian(
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6],
[1, 2, 3, 4, 5, 6]
)];