prettier
Felix Böhm
5 years ago
0 | 0 | module.exports = compile; |
1 | 1 | |
2 | 2 | var BaseFuncs = require("boolbase"), |
3 | trueFunc = BaseFuncs.trueFunc, | |
3 | trueFunc = BaseFuncs.trueFunc, | |
4 | 4 | falseFunc = BaseFuncs.falseFunc; |
5 | 5 | |
6 | 6 | /* |
7 | 7 | returns a function that checks if an elements index matches the given rule |
8 | 8 | highly optimized to return the fastest solution |
9 | 9 | */ |
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; | |
13 | 13 | |
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; | |
17 | 17 | |
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 | }; | |
23 | 34 | |
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; | |
27 | 38 | |
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 | } | |
33 | 44 | |
34 | a *= -1; //make `a` positive | |
45 | a *= -1; //make `a` positive | |
35 | 46 | |
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 | } |
0 | 0 | var parse = require("./parse.js"), |
1 | 1 | compile = require("./compile.js"); |
2 | 2 | |
3 | module.exports = function nthCheck(formula){ | |
4 | return compile(parse(formula)); | |
3 | module.exports = function nthCheck(formula) { | |
4 | return compile(parse(formula)); | |
5 | 5 | }; |
6 | 6 | |
7 | 7 | module.exports.parse = parse; |
8 | module.exports.compile = compile;⏎ | |
8 | module.exports.compile = compile; |
27 | 27 | "homepage": "https://github.com/fb55/nth-check", |
28 | 28 | "dependencies": { |
29 | 29 | "boolbase": "~1.0.0" |
30 | }, | |
31 | "prettier": { | |
32 | "tabWidth": 4 | |
30 | 33 | } |
31 | 34 | } |
7 | 7 | /* |
8 | 8 | parses a nth-check formula, returns an array of two numbers |
9 | 9 | */ |
10 | function parse(formula){ | |
11 | formula = formula.trim().toLowerCase(); | |
10 | function parse(formula) { | |
11 | formula = formula.trim().toLowerCase(); | |
12 | 12 | |
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); | |
19 | 19 | |
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 | } | |
23 | 25 | |
24 | var a; | |
26 | var a; | |
25 | 27 | |
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; | |
33 | 35 | |
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 | } | |
39 | 38 | } |
0 | 0 | var nthCheck = require("./"), |
1 | 1 | assert = require("assert"); |
2 | 2 | |
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 | ]; | |
4 | 15 | |
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 | }); | |
14 | 26 | } |
15 | 27 | |
16 | 28 | 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], | |
47 | 59 | |
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] | |
51 | 63 | }; |
52 | 64 | |
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 | }); | |
57 | 69 | } |
58 | 70 | |
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 | }); | |
63 | 75 | } |
64 | 76 | |
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 | }); | |
66 | 80 | |
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); | |
70 | 84 | |
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 | } | |
78 | 92 | } |
79 | 93 | |
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]; | |
83 | 97 | |
84 | if(a === 0 && b > 0) return [b - 1]; | |
98 | if (a === 0 && b > 0) return [b - 1]; | |
85 | 99 | |
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 | }); | |
92 | 106 | } |
93 | 107 | |
94 | 108 | process.stdout.write("- parser"); |