├── README.md └── androidUnlockPins.js /README.md: -------------------------------------------------------------------------------- 1 | # AndroidUnlockPattern 2 | Find all valid unlock pin pattern for android phone for a 3 by 3 grid 3 | -------------------------------------------------------------------------------- /androidUnlockPins.js: -------------------------------------------------------------------------------- 1 | /* find all valid android lock pin patterns 2 | 3 | Given an Android 3x3 key lock screen and two integers m and n, where 1 ≤ m ≤ n ≤ 9, 4 | count the total number of unlock patterns of the Android lock screen, 5 | which consist of minimum of m keys and maximum n keys. 6 | 7 | Rules for a valid pattern: 8 | 9 | 1. Each pattern must connect at least m keys and at most n keys. 10 | 2. All the keys must be distinct. 11 | 3. If the line connecting two consecutive keys in the pattern passes through any other keys, 12 | the other keys must have previously selected in the pattern. 13 | 4. No jumps through non selected key is allowed. 14 | 5. The order of keys used matters. 15 | 16 | 0 1 2 17 | 3 4 5 18 | 6 7 8 19 | 20 | */ 21 | 22 | function findAllLockPatterns(m, n) { 23 | 24 | var res = 0; 25 | var jumpMap = [[], [], [], [], [], [], [], [], []]; 26 | 27 | jumpMap[0][2] = 1; 28 | jumpMap[0][6] = 3; 29 | jumpMap[0][8] = 4; 30 | jumpMap[1][7] = 4; 31 | jumpMap[2][0] = 1; 32 | jumpMap[2][8] = 5; 33 | jumpMap[2][6] = 4; 34 | jumpMap[3][5] = 4; 35 | jumpMap[5][3] = 4; 36 | jumpMap[6][8] = 7; 37 | jumpMap[6][2] = 4; 38 | jumpMap[6][0] = 3; 39 | jumpMap[7][1] = 4; 40 | jumpMap[8][0] = 4; 41 | jumpMap[8][2] = 5; 42 | jumpMap[8][6] = 7; 43 | 44 | var visited = {}; 45 | 46 | // find pattern with min length m and max length n 47 | for(let i=m; i <= n; i++) { 48 | // find pattern for 0 to 8 49 | res += findPattern(visited, jumpMap, 0, i-1) * 4; 50 | res += findPattern(visited, jumpMap, 1, i-1) * 4; 51 | res += findPattern(visited, jumpMap, 4, i-1); 52 | } 53 | 54 | return res; 55 | } 56 | 57 | function findPattern(visited, jumpMap, start, remaining) { 58 | // 0 1 2 59 | // 3 4 5 60 | // 6 7 8 61 | 62 | if (remaining === 0) { 63 | // stop here since we found the complete length of the pattern and we are done 64 | return 1; // res is returned as 1 only here when remaining becomes 0 65 | } 66 | 67 | if (remaining < 0) { 68 | return 0; 69 | } 70 | 71 | // mark visited for start as 1 72 | visited[start] = true; 73 | 74 | var res = 0; 75 | 76 | // find all pins starting with pin "start" 77 | // search for the next pin "j" 78 | // total length of pin is "remaining" 79 | for (let j=0; j<9; j++) { 80 | // continue finding this pattern if pin j satisfies the following condition 81 | if (!visited[j] && (jumpMap[start][j] === 0 || visited[jumpMap[start][j]])) { 82 | // j now becomes like "start" for the next round 83 | // and we continue finding the remaining pins 84 | res += findPattern(visited, jumpMap, j, remaining-1); 85 | } 86 | } 87 | 88 | // reset visited 89 | visited[start] = false; 90 | 91 | return res; 92 | } 93 | 94 | 95 | console.log(findAllLockPatterns(1, 4)); --------------------------------------------------------------------------------