Skip to content

Instantly share code, notes, and snippets.

@jniac
Last active November 25, 2020 23:22
Show Gist options
  • Save jniac/eccdf28690f9630f403179adf4d2956f to your computer and use it in GitHub Desktop.
Save jniac/eccdf28690f9630f403179adf4d2956f to your computer and use it in GitHub Desktop.
get a n-dimensions array, iterate through indexes from a specified dimension
/**
* returns [1, 4, 12] from [4, 3, 2]
* @param {number[]} array
*/
function getArrayScale (array) {
let scale = 1
return array.map(dim => {
const x = scale
scale *= dim
return x
})
}
/**
* yields [0, 0], [1, 0], [0, 1], [1, 1] from [2, 2]
* @param {number[]} dimensions
*/
function* iterateDimensions(dimensions) {
let index = 0
let max = dimensions.reduce((t, x) => t * x)
const iterator = dimensions.map(() => 0)
while (true) {
yield [...iterator]
if (++index === max) {
break
}
let dimIndex = 0
while (iterator[dimIndex] === dimensions[dimIndex] -1) {
iterator[dimIndex] = 0
dimIndex++
}
iterator[dimIndex] = iterator[dimIndex] + 1
}
}
/**
* Should yield over iterator (and not array) to save space.
* @param {number[]} dimensions
* @param {number} dimIndex
*/
function* iterateDimensionsFrom(dimensions, dimIndex) {
const scales = getArrayScale(dimensions)
const getIndex = coords => coords.reduce((t, x, i) => t + x * scales[i], 0)
const beforeDimensions = dimensions.slice(0, dimIndex)
const afterDimensions = dimensions.slice(dimIndex + 1)
const otherDimensions = [...beforeDimensions, ...afterDimensions]
const max = dimensions[dimIndex]
for (let i = 0; i < max; i++) {
// here, the array is cooked, but it's suboptimal
yield [...iterateDimensions(otherDimensions)].map(coords => {
const fullCoords = [...coords.slice(0, dimIndex), i, ...coords.slice(dimIndex)]
return getIndex(fullCoords)
})
}
}
const format = a => a.map(a => a.map(n => `${n},`.padEnd(4, ' ')).join('')).join('\n')
console.log(format([...iterateDimensionsFrom([4, 3, 2], 0)]))
console.log(format([...iterateDimensionsFrom([4, 3, 2], 1)]))
console.log(format([...iterateDimensionsFrom([4, 3, 2], 2)]))
// output
// 0, 4, 8, 12, 16, 20,
// 1, 5, 9, 13, 17, 21,
// 2, 6, 10, 14, 18, 22,
// 3, 7, 11, 15, 19, 23,
// 0, 1, 2, 3, 12, 13, 14, 15,
// 4, 5, 6, 7, 16, 17, 18, 19,
// 8, 9, 10, 11, 20, 21, 22, 23,
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
// 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment