Last active
November 25, 2020 23:22
-
-
Save jniac/eccdf28690f9630f403179adf4d2956f to your computer and use it in GitHub Desktop.
get a n-dimensions array, iterate through indexes from a specified dimension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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