Codebase list node-nth-check / 91a7ce7
prettier Felix Böhm 5 years ago
5 changed file(s) with 151 addition(s) and 124 deletion(s). Raw diff Collapse all Expand all
00 module.exports = compile;
11
22 var BaseFuncs = require("boolbase"),
3 trueFunc = BaseFuncs.trueFunc,
3 trueFunc = BaseFuncs.trueFunc,
44 falseFunc = BaseFuncs.falseFunc;
55
66 /*
77 returns a function that checks if an elements index matches the given rule
88 highly optimized to return the fastest solution
99 */
10 function compile(parsed){
11 var a = parsed[0],
12 b = parsed[1] - 1;
10 function compile(parsed) {
11 var a = parsed[0],
12 b = parsed[1] - 1;
1313
14 //when b <= 0, a*n won't be possible for any matches when a < 0
15 //besides, the specification says that no element is matched when a and b are 0
16 if(b < 0 && a <= 0) return falseFunc;
14 //when b <= 0, a*n won't be possible for any matches when a < 0
15 //besides, the specification says that no element is matched when a and b are 0
16 if (b < 0 && a <= 0) return falseFunc;
1717
18 //when a is in the range -1..1, it matches any element (so only b is checked)
19 if(a ===-1) return function(pos){ return pos <= b; };
20 if(a === 0) return function(pos){ return pos === b; };
21 //when b <= 0 and a === 1, they match any element
22 if(a === 1) return b < 0 ? trueFunc : function(pos){ return pos >= b; };
18 //when a is in the range -1..1, it matches any element (so only b is checked)
19 if (a === -1)
20 return function(pos) {
21 return pos <= b;
22 };
23 if (a === 0)
24 return function(pos) {
25 return pos === b;
26 };
27 //when b <= 0 and a === 1, they match any element
28 if (a === 1)
29 return b < 0
30 ? trueFunc
31 : function(pos) {
32 return pos >= b;
33 };
2334
24 //when a > 0, modulo can be used to check if there is a match
25 var bMod = b % a;
26 if(bMod < 0) bMod += a;
35 //when a > 0, modulo can be used to check if there is a match
36 var bMod = b % a;
37 if (bMod < 0) bMod += a;
2738
28 if(a > 1){
29 return function(pos){
30 return pos >= b && pos % a === bMod;
31 };
32 }
39 if (a > 1) {
40 return function(pos) {
41 return pos >= b && pos % a === bMod;
42 };
43 }
3344
34 a *= -1; //make `a` positive
45 a *= -1; //make `a` positive
3546
36 return function(pos){
37 return pos <= b && pos % a === bMod;
38 };
39 }
47 return function(pos) {
48 return pos <= b && pos % a === bMod;
49 };
50 }
00 var parse = require("./parse.js"),
11 compile = require("./compile.js");
22
3 module.exports = function nthCheck(formula){
4 return compile(parse(formula));
3 module.exports = function nthCheck(formula) {
4 return compile(parse(formula));
55 };
66
77 module.exports.parse = parse;
8 module.exports.compile = compile;
8 module.exports.compile = compile;
2727 "homepage": "https://github.com/fb55/nth-check",
2828 "dependencies": {
2929 "boolbase": "~1.0.0"
30 },
31 "prettier": {
32 "tabWidth": 4
3033 }
3134 }
77 /*
88 parses a nth-check formula, returns an array of two numbers
99 */
10 function parse(formula){
11 formula = formula.trim().toLowerCase();
10 function parse(formula) {
11 formula = formula.trim().toLowerCase();
1212
13 if(formula === "even"){
14 return [2, 0];
15 } else if(formula === "odd"){
16 return [2, 1];
17 } else {
18 var parsed = formula.match(re_nthElement);
13 if (formula === "even") {
14 return [2, 0];
15 } else if (formula === "odd") {
16 return [2, 1];
17 } else {
18 var parsed = formula.match(re_nthElement);
1919
20 if(!parsed){
21 throw new SyntaxError("n-th rule couldn't be parsed ('" + formula + "')");
22 }
20 if (!parsed) {
21 throw new SyntaxError(
22 "n-th rule couldn't be parsed ('" + formula + "')"
23 );
24 }
2325
24 var a;
26 var a;
2527
26 if(parsed[1]){
27 a = parseInt(parsed[1], 10);
28 if(isNaN(a)){
29 if(parsed[1].charAt(0) === "-") a = -1;
30 else a = 1;
31 }
32 } else a = 0;
28 if (parsed[1]) {
29 a = parseInt(parsed[1], 10);
30 if (isNaN(a)) {
31 if (parsed[1].charAt(0) === "-") a = -1;
32 else a = 1;
33 }
34 } else a = 0;
3335
34 return [
35 a,
36 parsed[3] ? parseInt((parsed[2] || "") + parsed[3], 10) : 0
37 ];
38 }
36 return [a, parsed[3] ? parseInt((parsed[2] || "") + parsed[3], 10) : 0];
37 }
3938 }
00 var nthCheck = require("./"),
11 assert = require("assert");
22
3 var invalid = ["-", "- 1n", "-1 n", "2+0", "2n+-0", "an+b", "asdf", "b", "expr", "odd|even|x"];
3 var invalid = [
4 "-",
5 "- 1n",
6 "-1 n",
7 "2+0",
8 "2n+-0",
9 "an+b",
10 "asdf",
11 "b",
12 "expr",
13 "odd|even|x"
14 ];
415
5 function parseInvalid(){
6 invalid.forEach(function(formula){
7 assert.throws(function(){
8 nthCheck.parse(formula);
9 },
10 SyntaxError,
11 formula
12 );
13 });
16 function parseInvalid() {
17 invalid.forEach(function(formula) {
18 assert.throws(
19 function() {
20 nthCheck.parse(formula);
21 },
22 SyntaxError,
23 formula
24 );
25 });
1426 }
1527
1628 var valid = {
17 "1": [ 0, 1 ],
18 "2": [ 0, 2 ],
19 "3": [ 0, 3 ],
20 "5": [ 0, 5 ],
21 " 1 ": [ 0, 1 ],
22 " 5 ": [ 0, 5 ],
23 "+2n + 1": [ 2, 1 ],
24 "-1": [ 0, -1 ],
25 "-1n + 3": [ -1, 3 ],
26 "-1n+3": [ -1, 3 ],
27 "-n+2": [ -1, 2 ],
28 "-n+3": [ -1, 3 ],
29 "0n+3": [ 0, 3 ],
30 "1n": [ 1, 0 ],
31 "1n+0": [ 1, 0 ],
32 "2n": [ 2, 0 ],
33 "2n + 1": [ 2, 1 ],
34 "2n+1": [ 2, 1 ],
35 "3n": [ 3, 0 ],
36 "3n+0": [ 3, 0 ],
37 "3n+1": [ 3, 1 ],
38 "3n+2": [ 3, 2 ],
39 "3n+3": [ 3, 3 ],
40 "3n-1": [ 3, -1 ],
41 "3n-2": [ 3, -2 ],
42 "3n-3": [ 3, -3 ],
43 even: [ 2, 0 ],
44 n: [ 1, 0 ],
45 "n+2": [ 1, 2 ],
46 odd: [ 2, 1 ],
29 "1": [0, 1],
30 "2": [0, 2],
31 "3": [0, 3],
32 "5": [0, 5],
33 " 1 ": [0, 1],
34 " 5 ": [0, 5],
35 "+2n + 1": [2, 1],
36 "-1": [0, -1],
37 "-1n + 3": [-1, 3],
38 "-1n+3": [-1, 3],
39 "-n+2": [-1, 2],
40 "-n+3": [-1, 3],
41 "0n+3": [0, 3],
42 "1n": [1, 0],
43 "1n+0": [1, 0],
44 "2n": [2, 0],
45 "2n + 1": [2, 1],
46 "2n+1": [2, 1],
47 "3n": [3, 0],
48 "3n+0": [3, 0],
49 "3n+1": [3, 1],
50 "3n+2": [3, 2],
51 "3n+3": [3, 3],
52 "3n-1": [3, -1],
53 "3n-2": [3, -2],
54 "3n-3": [3, -3],
55 even: [2, 0],
56 n: [1, 0],
57 "n+2": [1, 2],
58 odd: [2, 1],
4759
48 //surprisingly, neither sizzle, qwery or nwmatcher cover these cases
49 "-4n+13": [-4, 13],
50 "-2n + 12": [-2, 12]
60 //surprisingly, neither sizzle, qwery or nwmatcher cover these cases
61 "-4n+13": [-4, 13],
62 "-2n + 12": [-2, 12]
5163 };
5264
53 function parseValid(){
54 Object.keys(valid).forEach(function(formula){
55 assert.deepEqual(nthCheck.parse(formula), valid[formula], formula);
56 });
65 function parseValid() {
66 Object.keys(valid).forEach(function(formula) {
67 assert.deepEqual(nthCheck.parse(formula), valid[formula], formula);
68 });
5769 }
5870
59 function testValid(){
60 Object.keys(valid).forEach(function(formula){
61 testFormula(valid[formula], formula);
62 });
71 function testValid() {
72 Object.keys(valid).forEach(function(formula) {
73 testFormula(valid[formula], formula);
74 });
6375 }
6476
65 var valArray = Array.apply(null, Array(2e3)).map(function(_, i){return i;});
77 var valArray = Array.apply(null, Array(2e3)).map(function(_, i) {
78 return i;
79 });
6680
67 function testFormula(formula, name){
68 var filtered = valArray.filter(nthCheck.compile(formula)),
69 iterated = stupidNth(formula);
81 function testFormula(formula, name) {
82 var filtered = valArray.filter(nthCheck.compile(formula)),
83 iterated = stupidNth(formula);
7084
71 try {
72 assert.deepEqual(filtered, iterated, name);
73 } catch(e){
74 e.expected = JSON.stringify(iterated) + " " + name;
75 e.actual = JSON.stringify(filtered) + " " + name;
76 throw e;
77 }
85 try {
86 assert.deepEqual(filtered, iterated, name);
87 } catch (e) {
88 e.expected = JSON.stringify(iterated) + " " + name;
89 e.actual = JSON.stringify(filtered) + " " + name;
90 throw e;
91 }
7892 }
7993
80 function stupidNth(formula, limit){
81 var a = formula[0],
82 b = formula[1];
94 function stupidNth(formula, limit) {
95 var a = formula[0],
96 b = formula[1];
8397
84 if(a === 0 && b > 0) return [b - 1];
98 if (a === 0 && b > 0) return [b - 1];
8599
86 //taken from qwery
87 return valArray.filter(function(val){
88 for(var i = b, l = valArray.length; ((a > 0) ? (i <= l) : (i >= 1)); i += a){
89 if(val === valArray[i - 1]) return true;
90 }
91 });
100 //taken from qwery
101 return valArray.filter(function(val) {
102 for (var i = b, l = valArray.length; a > 0 ? i <= l : i >= 1; i += a) {
103 if (val === valArray[i - 1]) return true;
104 }
105 });
92106 }
93107
94108 process.stdout.write("- parser");