Home Reference Source

scripts/experiment-properties/balancing/generators/latin_square_generator.js

  1. export { initialize_latin_square }
  2.  
  3. /**
  4. * Creates a random row generating function meeting the lating square restriction
  5. * usage:
  6. * sampler = latinCube(someRow)
  7. * newRow = sampler() | newRow = sampler(row)
  8. * @param {Array} row samples to be randomized
  9. * @returns {Function} row generating function
  10. */
  11. function latin_square (row) {
  12. var sN = row.length,
  13. rowCount = 0
  14.  
  15. // prepare array of row and col indices for pre-sorting
  16. var hSort = shuffle(sequence(sN)),
  17. vSort = shuffle(hSort.slice())
  18.  
  19. return function nextRow (countORtarget) {
  20. if (rowCount === sN) return countORtarget = null
  21. var target = Array.isArray(countORtarget) ? countORtarget
  22. : (countORtarget >= 0) ? Array(countORtarget)
  23. : Array(sN)
  24. if (target.length > sN) target.length = sN
  25.  
  26. for (var i = 0; i < target.length; ++i) {
  27. var idx = hSort[i] + vSort[rowCount]
  28. if (idx >= sN) idx -= sN
  29. target[i] = row[idx]
  30. }
  31. rowCount++
  32.  
  33. return target
  34. }
  35. }
  36. function sequence(n) {
  37. for (var i = 0, a=Array(n); i < n; ++i) a[i] = i
  38. return a
  39. }
  40. // modified from https://github.com/sindresorhus/array-shuffle
  41. function shuffle(arr) {
  42. var len = arr.length
  43. while (len) {
  44. var rnd = Math.floor(Math.random() * len--)
  45. var tmp = arr[len]
  46. arr[len] = arr[rnd]
  47. arr[rnd] = tmp
  48. }
  49. return arr
  50. }
  51.  
  52. function initialize_latin_square(size){
  53. var array = Array.apply(null, {length: size}).map(Number.call, Number);
  54. var sampler = latin_square(array);
  55. var row = sampler();
  56.  
  57. console.log("Latin square: " + row);
  58. return row;
  59. }