Skip to content

Instantly share code, notes, and snippets.

@hackape
Last active October 27, 2020 03:12
Show Gist options
  • Save hackape/7419a599ffc4d7ece38651118d0ad1f3 to your computer and use it in GitHub Desktop.
Save hackape/7419a599ffc4d7ece38651118d0ad1f3 to your computer and use it in GitHub Desktop.
Find all combinations from given ordered choices.

Combinations

Find all combinations from given ordered choices.

Implementation

function getAllCombinations<T>(slotsChoices: T[][]) {
  const searchSpaceSizes = slotsChoices.map(choices => choices.length)
  const solutionSize = searchSpaceSizes.reduce((a, b) => a * b)
  const slots = new Array(solutionSize).fill(slotsChoices)
  const solutions = slots.map((slotsChoices, i) => {
    const indexesToPick = decodeIndex(i, searchSpaceSizes)
    return indexesToPick.map((index, j) => {
      const choices = slotsChoices[j]
      return choices[index]
    })
  })
  return solutions
}

function decodeIndex(index: number, searchSpaceSizes: number[]) {
  const indexesToPick = []
  let divident = index
  for (let i = 0; i < searchSpaceSizes.length; i++) {
    const [quotient, remainder] = euclideanDivision(divident, searchSpaceSizes[i])
    indexesToPick[i] = remainder
    divident = quotient
  }
  return indexesToPick
}

function euclideanDivision(divident: number, divisor: number) {
  const remainder = divident % divisor;
  const quotient =  (divident - remainder) / divisor;
  return [quotient, remainder]
}

Usage

const slotsChoices = [
  [0, 1, 2, 3],
  [0, 1],
  [0, 1, 2]
]

const solutions = getAllCombinations(slotsChoices)
/**
solutions = [
  [0, 0, 0], [1, 0, 0], [2, 0, 0], [3, 0, 0], 
  [0, 1, 0], [1, 1, 0], [2, 1, 0], [3, 1, 0], 
  [0, 0, 1], [1, 0, 1], [2, 0, 1], [3, 0, 1], 
  [0, 1, 1], [1, 1, 1], [2, 1, 1], [3, 1, 1], 
  [0, 0, 2], [1, 0, 2], [2, 0, 2], [3, 0, 2], 
  [0, 1, 2], [1, 1, 2], [2, 1, 2], [3, 1, 2]
]
*/

Refs

https://stackoverflow.com/a/64138214/3617380

function getAllCombinations(slotsChoices) {
const searchSpaceSizes = slotsChoices.map(choices => choices.length);
const solutionSize = searchSpaceSizes.reduce((a, b) => a * b);
const slots = new Array(solutionSize).fill(slotsChoices);
const solutions = slots.map((slotsChoices, i) => {
const indexesToPick = decodeIndex(i, searchSpaceSizes);
return indexesToPick.map((index, j) => {
const choices = slotsChoices[j];
return choices[index];
});
});
return solutions;
}
function decodeIndex(index, searchSpaceSizes) {
const indexesToPick = [];
let divident = index;
for (let i = 0; i < searchSpaceSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(divident, searchSpaceSizes[i]);
indexesToPick[i] = remainder;
divident = quotient;
}
return indexesToPick;
}
function euclideanDivision(divident, divisor) {
const remainder = divident % divisor;
const quotient = (divident - remainder) / divisor;
return [quotient, remainder];
}
function getAllCombinations<T>(slotsChoices: T[][]) {
const searchSpaceSizes = slotsChoices.map(choices => choices.length)
const solutionSize = searchSpaceSizes.reduce((a, b) => a * b)
const slots = new Array(solutionSize).fill(slotsChoices)
const solutions = slots.map((slotsChoices, i) => {
const indexesToPick = decodeIndex(i, searchSpaceSizes)
return indexesToPick.map((index, j) => {
const choices = slotsChoices[j]
return choices[index]
})
})
return solutions
}
function decodeIndex(index: number, searchSpaceSizes: number[]) {
const indexesToPick = []
let divident = index
for (let i = 0; i < searchSpaceSizes.length; i++) {
const [quotient, remainder] = euclideanDivision(divident, searchSpaceSizes[i])
indexesToPick[i] = remainder
divident = quotient
}
return indexesToPick
}
function euclideanDivision(divident: number, divisor: number) {
const remainder = divident % divisor;
const quotient = (divident - remainder) / divisor;
return [quotient, remainder]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment