scripts/experiment-properties/balancing/generators/latin_square_generator.js
export { initialize_latin_square }
/**
* Creates a random row generating function meeting the lating square restriction
* usage:
* sampler = latinCube(someRow)
* newRow = sampler() | newRow = sampler(row)
* @param {Array} row samples to be randomized
* @returns {Function} row generating function
*/
function latin_square (row) {
var sN = row.length,
rowCount = 0
// prepare array of row and col indices for pre-sorting
var hSort = shuffle(sequence(sN)),
vSort = shuffle(hSort.slice())
return function nextRow (countORtarget) {
if (rowCount === sN) return countORtarget = null
var target = Array.isArray(countORtarget) ? countORtarget
: (countORtarget >= 0) ? Array(countORtarget)
: Array(sN)
if (target.length > sN) target.length = sN
for (var i = 0; i < target.length; ++i) {
var idx = hSort[i] + vSort[rowCount]
if (idx >= sN) idx -= sN
target[i] = row[idx]
}
rowCount++
return target
}
}
function sequence(n) {
for (var i = 0, a=Array(n); i < n; ++i) a[i] = i
return a
}
// modified from https://github.com/sindresorhus/array-shuffle
function shuffle(arr) {
var len = arr.length
while (len) {
var rnd = Math.floor(Math.random() * len--)
var tmp = arr[len]
arr[len] = arr[rnd]
arr[rnd] = tmp
}
return arr
}
function initialize_latin_square(size){
var array = Array.apply(null, {length: size}).map(Number.call, Number);
var sampler = latin_square(array);
var row = sampler();
console.log("Latin square: " + row);
return row;
}