Skip to content

Instantly share code, notes, and snippets.

@tchap
Last active December 8, 2015 09:45
Show Gist options
  • Save tchap/da961cc99cc7ed959a7f to your computer and use it in GitHub Desktop.
Save tchap/da961cc99cc7ed959a7f to your computer and use it in GitHub Desktop.
Compute cartesian product in JavaScript (ES6).
const cartProd = (...lists) => {
if (lists.length < 2) {
throw new Error('cartProd: need at least 2 lists as arguments');
}
const head = (list) => list[0];
const tail = (list) => list.slice(1);
const prepend = (head, tail) => [head, ...tail];
const push = (list, item) => {
list = list || [];
list.push(item);
return list;
};
try {
return genericCartProd(head, tail, prepend, push, ...lists);
} catch (err) {
if (err.message === '--- empty ---') {
return [];
}
throw err;
}
}
const genericCartProd = (head, tail, prepend, push, ...lists) => {
const hs = head(lists);
const ts = tail(lists);
// Cartesian product is an empty set in case one of the lists is empty.
if (hs.length === 0) {
throw new Error('--- empty ---');
}
// In case this is the last element, we want to turn
// [a, b, c] into [[a], [b], [c]] and end recursion.
if (ts.length === 0) {
return hs.map((x) => [x]);
}
// Get CP for tail.
const cps = genericCartProd(head, tail, prepend, push, ...ts);
// Prepend items from head to CP for tail.
var acc;
for (let hi of hs) {
for (let pi of cps) {
acc = push(acc, prepend(hi, pi));
}
}
return acc;
}
console.log(cartProd([1, 2], [3, 4], [5, 6]));
/*
[ [ 1, 3, 5 ],
[ 1, 3, 6 ],
[ 1, 4, 5 ],
[ 1, 4, 6 ],
[ 2, 3, 5 ],
[ 2, 3, 6 ],
[ 2, 4, 5 ],
[ 2, 4, 6 ] ]
*/
console.log(cartProd([1, 2], [3, 4], [5, 6], []));
/*
[]
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment