-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
185 lines (164 loc) · 4.56 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
"use strict";
module.exports.generate = function(input){
var elements = [];
var size = 0;
if(_isValidSize(input)){
return generateDefaultLatinSquare(input);
}
else if(_isValidElementsArr(input)){
elements = input.slice();
elements.sort();
size = elements.length;
return generateLatinSquare(elements);
}
else {
throw new TypeError('Expected an integer or array with unique elements');
}
};
module.exports.validate = function(lSquare){
return _validateLatinSquare(lSquare);
};
module.exports.isValidLatinSquare = function(lSquare){
var valid = _validateLatinSquare(lSquare);
if(valid === "") return true;
else return false;
};
//region Helper Function
function generateLatinSquare(elements){
if(_isValidElementsArr(elements)){
var lSquare = generateDefaultLatinSquare(elements.length);
var sq = lSquare;
for(var r=0; r< sq.length; r++ ){
for(var c=0; c < sq.length; c++){
lSquare[r][c] = elements[lSquare[r][c] - 1]
}
}
return lSquare;
}
else {
return null;
}
}
function generateDefaultLatinSquare(size){
var lSquare = null;
if(_isValidSize(size)){
lSquare = new Array(size);
var elements = [];
for(var i = 1; i<= size; i++){
elements.push(i);
}
for( i = 0; i< size; i++){
lSquare[i] = new Array(size);
}
var row = elements.slice();
row = _shuffleArr(row);
lSquare[0] = row;
for(var r = 1; r< size; r++){
for(var c = 0; c < size; c++){
var items = elements.slice();
items = _shuffleArr(items);
for(var c1 = 0; c1 < c; c1++){
_removeItemFromArrayByValue(items, lSquare[r][c1]);
}
for(var r1 = 0; r1 < r; r1++){
_removeItemFromArrayByValue(items, lSquare[r1][c]);
}
if(items[0] === undefined){
return generateDefaultLatinSquare(size);
}
else{
lSquare[r][c] = items[0];
}
}
}
}
return lSquare;
}
function _isValidSize(n){
return (typeof n === 'number') && (n % 1 === 0) && n > 0 ;
}
function _isValidElementsArr(arr){
/*
* array length should be > 0 and each element in the array should be unique.
* */
if(!Array.isArray(arr)){
return false;
}
if(_isValidSize(arr.length)){
arr.sort();
for ( var i = 1; i < arr.length; i++ ){
if(arr[i-1] == arr[i])
return false;
}
return true;
}
else {
return false;
}
}
function _validateLatinSquare(lSquare){
var i, j, size ;
//Check lSquare should be an 2d array with size > 0
if(!Array.isArray(lSquare)){
return "Not An Array";
}
size = lSquare.length;
if(!_isValidSize(size)){
return "Invalid Size";
}
for(i in lSquare){
if(!Array.isArray(lSquare[i])){
return "Not a valid 2D Array";
}
var sz = (lSquare[i]).length;
if(!_isValidSize(sz)){
return "Not a valid sized 2D Array";
}
if(sz !== size){
return "Not a valid 2D square Array";
}
}
//Check-6 basic latin square logic - item should be unique across row and col
for(var r = 0; r < size; r++){
for(var c = 0; c < size; c++){
var item = lSquare[r][c];
for(var r1 = 0; r1< size; r1++){
if(r !== r1 && lSquare[r1][c] === lSquare[r][c]) {
return item + " repeated in column " + c;
}
}
for(var c1 = 0; c1< size; c1++){
if(c !== c1 && lSquare[r][c1] === lSquare[r][c]) {
return item + " repeated in row " + r;
}
}
}
}
return "";
}
function _shuffleArr(arr){
if(!Array.isArray(arr)){
throw new TypeError('Expected an array');
}
var result = arr.slice();
var len = arr.length;
var rnd,tmp;
while(len){
rnd = Math.floor(Math.random() * len--);
tmp = result[len];
result[len] = result[rnd];
result[rnd] = tmp;
}
return result;
}
function _removeItemFromArrayByValue(arr) {
var what, a = arguments, L = a.length, ax;
while (L > 1 && arr.length) {
what = a[--L];
while ((ax= arr.indexOf(what)) !== -1) {
arr.splice(ax, 1);
}
}
return arr;
}
//endregion