├── package.json ├── s01e08_Anagram └── anagram.js ├── .gitignore ├── s01e07_ArrayBypass └── arrayBypass.js ├── s01e04_Stack └── stack.js ├── s01e01_Array └── array.js ├── s01e02_Numbers └── numbers.js ├── s01e06_ArrayMethods └── arrayMethods.js ├── s01e03_Matrix └── matrix.js ├── s01e05_String └── string.js ├── s01e11_LinkedList └── linkedList.js └── s01e12_Tree └── tree.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rs-series", 3 | "version": "1.0.0", 4 | "description": "Materials for small lectures about JavaScript for The Rolling Scopes School.", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "nodemon s01e12_Tree/tree.js", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/ToshaBely/rs-series.git" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "bugs": { 17 | "url": "https://github.com/ToshaBely/rs-series/issues" 18 | }, 19 | "homepage": "https://github.com/ToshaBely/rs-series#readme", 20 | "devDependencies": { 21 | "nodemon": "^2.0.7" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /s01e08_Anagram/anagram.js: -------------------------------------------------------------------------------- 1 | function checkAnagrams(left, right) { 2 | if (left.length !== right.length) { 3 | return false; 4 | } 5 | 6 | let leftMap = {}; 7 | for (let i = 0; i < left.length; i++) { 8 | let symbol = left[i]; 9 | leftMap[symbol] = (leftMap[symbol] || 0) + 1; 10 | } 11 | 12 | for (let i = 0; i < right.length; i++) { 13 | let symbol = right[i]; 14 | 15 | if (!leftMap[symbol]) { 16 | // if there is no symbol or count is equal 0 17 | return false; 18 | } 19 | 20 | leftMap[symbol] = leftMap[symbol] - 1; 21 | } 22 | 23 | return true; 24 | } 25 | 26 | console.log('s01e08 - Anagram'); 27 | 28 | console.log(' abc cba', checkAnagrams('abc', 'cba')); 29 | console.log(' abc cbaa', checkAnagrams('abc', 'cbaa')); 30 | console.log(' aabc cbaa', checkAnagrams('aabc', 'cbaa')); 31 | console.log(' abcz abcx', checkAnagrams('abcz', 'abcx')); 32 | console.log(' aabc cbaa', checkAnagrams('aabc', 'cbaa')); 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Created by https://www.gitignore.io/api/node 3 | # Edit at https://www.gitignore.io/?templates=node 4 | 5 | ### Node ### 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | node_modules/ 46 | jspm_packages/ 47 | 48 | # TypeScript v1 declaration files 49 | typings/ 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional REPL history 58 | .node_repl_history 59 | 60 | # Output of 'npm pack' 61 | *.tgz 62 | 63 | # Yarn Integrity file 64 | .yarn-integrity 65 | 66 | # dotenv environment variables file 67 | .env 68 | .env.test 69 | 70 | # parcel-bundler cache (https://parceljs.org/) 71 | .cache 72 | 73 | # next.js build output 74 | .next 75 | 76 | # nuxt.js build output 77 | .nuxt 78 | 79 | # vuepress build output 80 | .vuepress/dist 81 | 82 | # Serverless directories 83 | .serverless/ 84 | 85 | # FuseBox cache 86 | .fusebox/ 87 | 88 | # DynamoDB Local files 89 | .dynamodb/ 90 | 91 | # End of https://www.gitignore.io/api/node 92 | -------------------------------------------------------------------------------- /s01e07_ArrayBypass/arrayBypass.js: -------------------------------------------------------------------------------- 1 | function getCommentsByPostId(commentList, postId) { 2 | console.log(`\nGet all comments for post with id = ${postId}:`); 3 | 4 | let comments = commentList 5 | .filter( comment => comment.postId === postId ) 6 | .map( comment => comment.text ); 7 | 8 | console.log(' comments:', comments); 9 | } 10 | 11 | function getAuthorNames(commentList) { 12 | console.log('\nGet author names:'); 13 | 14 | let authors = commentList 15 | .map( comment => comment.author ) 16 | .filter( (author, index, currentList) => 17 | currentList.findIndex( item => item.id === author.id ) === index 18 | ) 19 | .map( author => author.name ); 20 | 21 | console.log(' authors:', authors); 22 | } 23 | 24 | function getAuthorsStatistics(commentList) { 25 | console.log('\nGet authors statistics: '); 26 | 27 | let statistics = commentList 28 | .map( comment => comment.author.id ) 29 | .reduce( (dict, item) => { 30 | dict[item] = (dict[item] || 0) + 1; 31 | return dict; 32 | }, {}); 33 | 34 | console.log(' statistics:', statistics); 35 | } 36 | 37 | 38 | console.log('s01e07 - Array Bypass'); 39 | 40 | let commentList = [ 41 | { 42 | id: '#com1', 43 | author: { id: '#aut1', name: 'John Doe'}, 44 | text: 'Cool!', 45 | postId: '#post1', 46 | }, 47 | { 48 | id: '#com2', 49 | author: { id: '#aut1', name: 'John Doe'}, 50 | text: 'Cool!', 51 | postId: '#post2', 52 | }, 53 | { 54 | id: '#com3', 55 | author: { id: '#aut2', name: 'Anthony Hopkins'}, 56 | text: 'Nice comment, John! :)', 57 | postId: '#post1', 58 | }, 59 | { 60 | id: '#com4', 61 | author: { id: '#aut1', name: 'John Doe'}, 62 | text: 'Thanks!', 63 | postId: '#post1', 64 | }, 65 | ]; 66 | 67 | console.log('\n[commentList]:'); 68 | commentList.forEach( comment => console.log(comment) ); 69 | 70 | // getCommentsByPostId(commentList, '#post1'); 71 | // getAuthorNames(commentList); 72 | // getAuthorsStatistics(commentList); 73 | -------------------------------------------------------------------------------- /s01e04_Stack/stack.js: -------------------------------------------------------------------------------- 1 | // Stack structure: 2 | // LIFO - Last In First Out 3 | 4 | // ------------------------ 5 | // | 1 2 3 4 ... <-> 6 | // ------------------------ 7 | 8 | // Base operations: PUSH / POP / TOP / SIZE / IS_EMPTY 9 | 10 | function stackOnArrayExample() { 11 | console.log('Stack on Array example:'); 12 | 13 | let stack = []; 14 | 15 | console.log(' Push fake call stack:'); 16 | 17 | console.log(' push Outer'); 18 | stack.push('Outer'); 19 | 20 | console.log(' push Inner'); 21 | stack.push('Inner'); 22 | 23 | console.log(' push Super-Inner'); 24 | stack.push('Super-Inner'); 25 | 26 | console.log(' push Super-Super-Inner'); 27 | stack.push('Super-Super-Inner'); 28 | 29 | console.log(' Execute fake call stack:'); 30 | 31 | while(stack.length) { 32 | let operation = stack.pop(); 33 | 34 | console.log(' execute -', operation); 35 | } 36 | } 37 | 38 | function bracketsIssue() { 39 | console.log('Brackets issue:'); 40 | 41 | const OPEN_BRACKETS = ['(', '{']; 42 | const BRACKETS_PAIR = { 43 | [')']: '(', 44 | ['}']: '{', 45 | }; 46 | 47 | function isBracketsOk(str) { 48 | let stack = []; 49 | 50 | for (let i = 0; i < str.length; i++) { 51 | let currentSymbol = str[i]; 52 | 53 | if (OPEN_BRACKETS.includes(currentSymbol)) { 54 | stack.push(currentSymbol); 55 | } else { 56 | if (stack.length === 0) { 57 | return false; 58 | } 59 | 60 | let topElement = stack[stack.length - 1]; 61 | 62 | if (BRACKETS_PAIR[currentSymbol] === topElement) { 63 | stack.pop(); 64 | } else { 65 | return false; 66 | } 67 | } 68 | } 69 | 70 | return stack.length === 0; 71 | } 72 | 73 | console.log(' check case - ()(()()) -', isBracketsOk('()(()())')); 74 | console.log(' check case - ())(() -', isBracketsOk('())(()')); 75 | console.log(' check case - (){}({}()) -', isBracketsOk('(){}({}())')); 76 | console.log(' check case - (}({}()) -', isBracketsOk('(}({}())')); 77 | console.log(' check case - ((()) -', isBracketsOk('((())')); 78 | } 79 | 80 | console.log('s01e04 - Stack\n'); 81 | 82 | stackOnArrayExample(); 83 | 84 | bracketsIssue(); 85 | 86 | // Brackets examples: 87 | // ()(()()) - OK 88 | // ())(() - WRONG 89 | 90 | // (){}({}()) - OK 91 | // (}({}()) - WRONG 92 | -------------------------------------------------------------------------------- /s01e01_Array/array.js: -------------------------------------------------------------------------------- 1 | // Array structure: 2 | // [ elem_1, elem_2, elem_3, ..., elem_n ] 3 | // 4 | //idx: 0 1 2 n-1 5 | 6 | 7 | // MDN documentation about Array: 8 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array 9 | 10 | function arrayCreation() { 11 | let arrayWithInitSize = new Array(4); 12 | let arrayWithOneValue = new Array('5'); 13 | let arrayWithPreset = new Array(5, 6); 14 | let arrayWithInitValue = Array.of(4); 15 | let arrayWithInitValues = Array.of(4, 5, 6); 16 | let simpleWayArray = ['a', 'b', 'c']; // preferrable way 17 | 18 | console.log('\nArray creation:'); 19 | console.log('arrayWithInitSize:', arrayWithInitSize); 20 | console.log('arrayWithOneValue:', arrayWithOneValue); 21 | console.log('arrayWithPreset:', arrayWithPreset); 22 | console.log('arrayWithInitValue:', arrayWithInitValue); 23 | console.log('arrayWithInitValues:', arrayWithInitValues); 24 | console.log('simpleWayArray:', simpleWayArray); 25 | } 26 | 27 | function arrayBypass() { 28 | function logEachElement(array) { 29 | for (let i = 0; i < array.length; i++) { 30 | console.log(`[elem with index ${i}] is ${array[i]}`); 31 | } 32 | } 33 | 34 | function findSum(array) { 35 | logEachElement(array); 36 | 37 | let sum = 0; 38 | 39 | for (let i = 0; i < array.length; i++) { 40 | sum += array[i]; 41 | } 42 | 43 | console.log(`sum = ${sum}`); 44 | } 45 | 46 | function findMin(array) { 47 | let min = array.length ? array[0] : 0; 48 | 49 | for (let i = 0; i < array.length; i++) { 50 | if (array[i] < min) { 51 | min = array[i]; 52 | } 53 | } 54 | 55 | console.log(`min is ${min}`); 56 | } 57 | 58 | function findAvg(array) { 59 | logEachElement(array); 60 | 61 | let sum = 0; 62 | 63 | for (let i = 0; i < array.length; i++) { 64 | sum += array[i]; 65 | } 66 | 67 | let avg = array.length ? sum / array.length : 0; 68 | 69 | console.log(`avg = ${avg}`); 70 | } 71 | 72 | console.log('\nArray bypass:'); 73 | 74 | let array = [21, 22, 23, 24, 25, 26, 27]; 75 | logEachElement(array); 76 | 77 | // array = [5, 1, 10, 23]; 78 | // findSum(array); 79 | // findMin(array); 80 | // findAvg(array); 81 | } 82 | 83 | console.log('s01e01 - Array\n'); 84 | arrayCreation(); 85 | // arrayBypass(); 86 | -------------------------------------------------------------------------------- /s01e02_Numbers/numbers.js: -------------------------------------------------------------------------------- 1 | function logDigits(num) { 2 | function dividing(num) { 3 | console.log('\nLog num digits dividing by 10:'); 4 | 5 | let digit; 6 | 7 | console.log(`\nNumber is ${num}`); 8 | 9 | while(num) { 10 | digit = num % 10; 11 | num = Math.floor(num / 10); 12 | 13 | console.log(` next digit - ${digit}`); 14 | } 15 | } 16 | 17 | function fromString(num) { 18 | console.log('\nLog num digits casting to string:'); 19 | 20 | let str = num.toString(); 21 | let digit; 22 | 23 | console.log(`\nNumber is ${num}`); 24 | 25 | for (let i = 0; i < str.length; i++) { 26 | digit = str[i]; 27 | console.log(` next digit - ${digit}`); 28 | } 29 | } 30 | 31 | dividing(num); 32 | fromString(num); 33 | } 34 | 35 | function toBinaryString(num) { 36 | let bin = num.toString(2); 37 | 38 | console.log(`\n${num} as binary string is ${bin}`); 39 | } 40 | 41 | function sumDigit(num) { 42 | console.log(`\nNumber is ${num}`); 43 | 44 | let sum = 0; 45 | 46 | while(num) { 47 | sum += num % 10; 48 | num = Math.floor(num / 10); 49 | } 50 | 51 | console.log(` digits sum is ${sum}`); 52 | } 53 | 54 | function reverse(num) { 55 | console.log(`\nNumber is ${num}`); 56 | 57 | let reversed = 0; 58 | 59 | while(num) { 60 | reversed = reversed * 10 + num % 10; 61 | num = Math.floor(num / 10); 62 | } 63 | 64 | console.log(` reversed num is ${reversed}`); // think about zero at the end of num 65 | } 66 | 67 | function isOddNumber(num) { 68 | console.log(`\nCheck is ${num} odd:`); 69 | 70 | let isOdd = Boolean(num % 2); 71 | console.log(` div by 2 - ${isOdd}`); 72 | 73 | isOdd = Boolean(num & 1); 74 | console.log(` logical AND with 1 - ${isOdd}`); 75 | } 76 | 77 | function isSimple(num) { 78 | if (num === 2) { 79 | return true; 80 | } 81 | 82 | for (let i = 2; i <= Math.sqrt(num); i++) { 83 | if (num % i === 0) { 84 | return false; 85 | } 86 | } 87 | 88 | return true; 89 | } 90 | 91 | console.log('s01e02 - Numbers\n'); 92 | 93 | let num = 65123; 94 | // logDigits(num); 95 | 96 | // toBinaryString(5); 97 | // toBinaryString(13); 98 | // toBinaryString(num); 99 | 100 | // sumDigit(num); 101 | 102 | // reverse(num); 103 | 104 | // isOddNumber(num); 105 | // isOddNumber(4); 106 | 107 | // let simple = isSimple(num); 108 | // console.log(`\nIs ${num} simple - ${simple}`); 109 | 110 | // simple = isSimple(23); 111 | // console.log(`\nIs ${23} simple - ${simple}`); 112 | 113 | // simple = isSimple(24); 114 | // console.log(`\nIs ${24} simple - ${simple}`); 115 | -------------------------------------------------------------------------------- /s01e06_ArrayMethods/arrayMethods.js: -------------------------------------------------------------------------------- 1 | function arrayHasSome() { 2 | console.log('\nHas Some:'); 3 | 4 | function hasSome(array, checkFn) { 5 | for (let i = 0; i < array.length; i++) { 6 | if ( checkFn(array[i]) ) { 7 | return true; 8 | } 9 | } 10 | 11 | return false; 12 | } 13 | 14 | let arr = [1, 2, 4, 8, 16]; 15 | 16 | console.log(' array:', arr, '\n'); 17 | 18 | console.log(' has > 5:', hasSome( arr, (item) => item > 5 )); 19 | console.log(' has > 20:', hasSome( arr, (item) => item > 20 )); 20 | 21 | // console.log(' has > 5 .some:', arr.some( (item) => item > 5 )); 22 | // console.log(' has > 20 .some:', arr.some( (item) => item > 20 )); 23 | } 24 | 25 | function arrayIsEvery() { 26 | console.log('\nIs Every:'); 27 | 28 | function isEvery(array, checkFn) { 29 | for (let i = 0; i < array.length; i++) { 30 | if ( !checkFn(array[i]) ) { 31 | return false; 32 | } 33 | } 34 | 35 | return true; 36 | } 37 | 38 | let arr = [1, 2, 4, 8, 16]; 39 | 40 | console.log(' array:', arr, '\n'); 41 | 42 | console.log(' is every < 5:', isEvery( arr, (item) => item < 5 )); 43 | console.log(' is every < 100:', isEvery( arr, (item) => item < 100 )); 44 | 45 | // console.log(' is every < 5 .every:', arr.every( (item) => item < 5 )); 46 | // console.log(' is every < 100 .every:', arr.every( (item) => item < 100 )); 47 | } 48 | 49 | function arrayTransform() { 50 | console.log('\nTransform:'); 51 | 52 | function transform(array, transformer) { 53 | let result = []; 54 | 55 | for (let i = 0; i < array.length; i++) { 56 | result.push( 57 | transformer(array[i]) 58 | ); 59 | } 60 | 61 | return result; 62 | } 63 | 64 | let arr = [1, 2, 4, 8, 16]; 65 | 66 | console.log(' before:', arr, '\n'); 67 | 68 | let transformed = transform( arr, (item) => item * 10 ); 69 | console.log(' after transformation:', transformed); 70 | 71 | // let res = arr.map( (item) => item * 10 ); 72 | // console.log(' after .map:', res); 73 | } 74 | 75 | function arrayFilter() { 76 | console.log('\nFilter:'); 77 | 78 | function filter(array, checkFn) { 79 | let result = []; 80 | 81 | for (let i = 0; i < array.length; i++) { 82 | if ( checkFn(array[i]) ) { 83 | result.push(array[i]); 84 | } 85 | } 86 | 87 | return result; 88 | } 89 | 90 | let arr = [1, 2, 4, 8, 16]; 91 | 92 | console.log(' before:', arr, '\n'); 93 | 94 | let filtered = filter( arr, (item) => item > 5 ); 95 | console.log(' after filtration:', filtered); 96 | 97 | // let res = arr.filter( (item) => item > 5 ); 98 | // console.log(' after .filter:', res); 99 | } 100 | 101 | 102 | console.log('s01e06 - Array Methods'); 103 | arrayHasSome(); 104 | // arrayIsEvery(); 105 | // arrayTransform(); 106 | // arrayFilter(); 107 | -------------------------------------------------------------------------------- /s01e03_Matrix/matrix.js: -------------------------------------------------------------------------------- 1 | // Matrix structure: 2 | // 3 | // # 0 1 2 4 | // 5 | // 0 [ [1, 2, 3], 6 | // 1 [4, 5, 6], 7 | // 2 [7, 8, 9] ] 8 | // 9 | 10 | function logEachMatrixItem(matrix) { 11 | console.log('\nLog each matrix item:'); 12 | 13 | for (let i = 0; i < matrix.length; i++) { 14 | for (let j = 0; j < matrix[i].length; j++) { 15 | console.log(` item {${i}, ${j}} - ${matrix[i][j]}`); 16 | } 17 | } 18 | } 19 | 20 | function showMatrix(matrix) { 21 | console.log('\nShow matrix:'); 22 | 23 | for (let i = 0; i < matrix.length; i++) { 24 | console.log( matrix[i].join(' ') ); 25 | } 26 | } 27 | 28 | function showSumByRow(matrix) { 29 | console.log('\nShow sum by row:'); 30 | 31 | let sumResults = []; 32 | let sum; 33 | 34 | for (let i = 0; i < matrix.length; i++) { 35 | sum = 0; 36 | 37 | for (let j = 0; j < matrix[i].length; j++) { 38 | sum += matrix[i][j]; 39 | } 40 | 41 | sumResults.push(sum); 42 | } 43 | 44 | console.log(' result -', sumResults); 45 | } 46 | 47 | function findColumnsWithZero(matrix) { 48 | // consider that we have matrix with some data 49 | 50 | console.log('\nFind columns with 0:'); 51 | 52 | let columnsWithZeroIdx = []; 53 | 54 | let columnCount = matrix[0].length; 55 | 56 | for (let i = 0; i < columnCount; i++) { 57 | for (let j = 0; j < matrix.length; j++) { 58 | if (matrix[j][i] === 0) { 59 | columnsWithZeroIdx.push(i); 60 | break; 61 | } 62 | } 63 | } 64 | 65 | console.log(' result indexes -', columnsWithZeroIdx); 66 | } 67 | 68 | function snakeBypass(matrix) { 69 | console.log('\nSnake bypass:'); 70 | 71 | for (let i = 0; i < matrix.length; i++) { 72 | for (let j = 0; j < matrix[i].length; j++) { 73 | let columnIdx = i % 2 === 0 74 | ? j 75 | : (matrix[i].length - j - 1); 76 | 77 | console.log( matrix[i][columnIdx] ); 78 | } 79 | } 80 | } 81 | 82 | function logMainDiag(matrix) { 83 | console.log('\nMain diag:'); 84 | 85 | for (let i = 0; i < matrix.length; i++) { 86 | console.log( matrix[i][i] ); 87 | } 88 | } 89 | 90 | function logSideDiag(matrix) { 91 | console.log('\nSide diag:'); 92 | 93 | let n = matrix.length; 94 | 95 | for (let i = 0; i < n; i++) { 96 | console.log( matrix[i][n - i - 1] ); 97 | } 98 | } 99 | 100 | function showBottomMainTriangle(matrix) { 101 | console.log('\nBottom main triangle:'); 102 | 103 | let row; 104 | 105 | for (let i = 0; i < matrix.length; i++) { 106 | row = []; 107 | 108 | for (let j = 0; j <= i; j++) { 109 | // action 110 | row.push( matrix[i][j] ); 111 | } 112 | 113 | console.log( row.join(' ') ); 114 | } 115 | } 116 | 117 | console.log('s01e03 - Matrix\n'); 118 | 119 | let matrix = [ 120 | [1, 2, 3, 4], 121 | [5, 6, 7, 8], 122 | [0, 3, 6, 9], 123 | [6, 8, 0, 2], 124 | ]; 125 | 126 | // logEachMatrixItem(matrix); 127 | // showMatrix(matrix); 128 | 129 | // showSumByRow(matrix); 130 | 131 | // findColumnsWithZero(matrix); 132 | 133 | // let smallMatrix = [ 134 | // [1, 2, 3], 135 | // [4, 5, 6], 136 | // [7, 8, 9], 137 | // ]; 138 | // showMatrix(smallMatrix); 139 | // snakeBypass(smallMatrix); 140 | 141 | // logMainDiag(matrix); 142 | // logSideDiag(matrix); 143 | 144 | // showMatrix(matrix); 145 | // showBottomMainTriangle(matrix); 146 | -------------------------------------------------------------------------------- /s01e05_String/string.js: -------------------------------------------------------------------------------- 1 | // String: 2 | // 'A BC' -> [65, 32, 66, 67] 3 | 4 | // .charCodeAt(idx) 5 | // String.fromCharCode() 6 | 7 | function showStringCharCodeList(str) { 8 | console.log('\nShow charcode list:'); 9 | 10 | for(let i = 0; i < str.length; i++) { 11 | console.log(` "${str[i]}" - ${str.charCodeAt(i)}`); 12 | } 13 | } 14 | 15 | function logSymbolsByCharCodeList(charCodeList) { 16 | console.log('\nShow symbols by charcode list:'); 17 | 18 | charCodeList.forEach((charCode) => { 19 | let symbol = String.fromCharCode(charCode); 20 | 21 | console.log(` [${charCode}] - "${symbol}"`); 22 | }); 23 | } 24 | 25 | function isPalindrome(str) { 26 | str = str.replace(/ /g, ''); 27 | 28 | let len = str.length; 29 | 30 | for (let i = 0; i < len / 2; i++) { 31 | if (str[i] !== str[len - i - 1]) { 32 | return false; 33 | } 34 | } 35 | 36 | return true; 37 | } 38 | 39 | function wordCount(str) { 40 | console.log('\nCalculate word count'); 41 | // check commented code: 42 | 43 | // let wordList = str.split(' '); 44 | // let wordList = str.split(/\s/); 45 | // let wordList = str.split(/\s+/); 46 | 47 | let wordList = str.trim().split(/\s+/); 48 | 49 | console.log(` String "${str}" contains ${wordList.length} word(s)"`); 50 | } 51 | 52 | function vigenereEncode(text, key) { 53 | let kf = Math.ceil(text.length / key.length); 54 | key = key.repeat(kf); 55 | 56 | let codeA = 'A'.charCodeAt(0); 57 | let abcCount = 26; 58 | 59 | let result = []; 60 | 61 | for (let i = 0; i < text.length; i++) { 62 | if (text[i] === ' ') { 63 | result.push(text[i]); 64 | } else { 65 | let letterIdx = text.charCodeAt(i) - codeA; 66 | let shift = key.charCodeAt(i) - codeA; 67 | 68 | result.push( 69 | String.fromCharCode( codeA + (letterIdx + shift) % abcCount ) 70 | ); 71 | } 72 | } 73 | 74 | return result.join(''); 75 | } 76 | 77 | function vigenereDecode(text, key) { 78 | let kf = Math.ceil(text.length / key.length); 79 | key = key.repeat(kf); 80 | 81 | let codeA = 'A'.charCodeAt(0); 82 | let abcCount = 26; 83 | 84 | let result = []; 85 | 86 | for (let i = 0; i < text.length; i++) { 87 | if (text[i] === ' ') { 88 | result.push(text[i]); 89 | } else { 90 | let letterIdx = text.charCodeAt(i) - codeA; 91 | let shift = key.charCodeAt(i) - codeA; 92 | 93 | result.push( 94 | String.fromCharCode( codeA + (letterIdx - shift + abcCount) % abcCount ) 95 | ); 96 | } 97 | } 98 | 99 | return result.join(''); 100 | } 101 | 102 | console.log('s01e05 - String\n'); 103 | 104 | showStringCharCodeList('Aa BC'); 105 | 106 | logSymbolsByCharCodeList([88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]); 107 | 108 | // console.log('check "abcba" is palindrome -', isPalindrome('abcba')); 109 | // console.log('check "abc" is palindrome -', isPalindrome('abc')); 110 | // console.log('check "а роза азора" is palindrome -', isPalindrome('а роза азора')); 111 | 112 | // wordCount(' abc cde fgh'); 113 | 114 | 115 | // console.log('Encoded "BBB" with key "AB" -', vigenereEncode('BBB', 'AB')); 116 | 117 | 118 | // let key = 'JAVASCRIPT'; 119 | 120 | // let secretText = vigenereEncode('MY NAME IS ANTON', key); 121 | // console.log(`Secret text [key="${key}"] - ${secretText}`); 122 | 123 | // let decodedSecret = vigenereDecode(secretText, key); 124 | // console.log(`Decoded text [key="${key}"] - ${decodedSecret}`); 125 | -------------------------------------------------------------------------------- /s01e11_LinkedList/linkedList.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(value) { 3 | this.value = value; 4 | this.next = null; 5 | } 6 | } 7 | 8 | // { value: 1, next: } -> { value: 2, next: null } 9 | 10 | class LinkedList { 11 | constructor() { 12 | this.head = null; 13 | this.length = 0; 14 | } 15 | 16 | add(value) { 17 | if (this.length === 0) { 18 | this.head = new Node(value); 19 | } else { 20 | let current = this.head; 21 | 22 | // move to the last node 23 | while(current.next) { 24 | current = current.next; 25 | } 26 | 27 | current.next = new Node(value); 28 | } 29 | 30 | this.length++; 31 | } 32 | 33 | insert(position, value) { 34 | if (position < 0 || position > this.length) { 35 | return false; 36 | } 37 | 38 | let node = new Node(value); 39 | 40 | if (position === 0) { 41 | node.next = this.head; 42 | this.head = node; 43 | } else { 44 | let current = this.head; 45 | let prev = null; 46 | 47 | let index = 0; 48 | 49 | while (index < position) { 50 | prev = current; 51 | current = current.next; 52 | index++; 53 | } 54 | 55 | prev.next = node; 56 | node.next = current; 57 | } 58 | 59 | this.length++; 60 | } 61 | 62 | get(position) { 63 | if (position < 0 || this.length <= position ) { 64 | return; 65 | } 66 | 67 | let current = this.head; 68 | let index = 0; 69 | 70 | while (index < position) { 71 | current = current.next; 72 | index++; 73 | } 74 | 75 | return current.value; 76 | } 77 | 78 | removeAt(position) { 79 | if (position < 0 || position >= this.length) { 80 | return null; 81 | } 82 | 83 | let current = this.head; 84 | 85 | if (position === 0) { 86 | this.head = current.next; 87 | } else { 88 | let prev = null; 89 | let index = 0; 90 | 91 | while (index < position) { 92 | prev = current; 93 | current = current.next; 94 | index++; 95 | } 96 | 97 | prev.next = current.next; 98 | } 99 | 100 | this.length--; 101 | return current.value; 102 | } 103 | 104 | remove(element) { 105 | this.removeAt( this.indexOf(element) ); 106 | } 107 | 108 | indexOf(element) { 109 | let current = this.head; 110 | let index = 0; 111 | 112 | while (current) { 113 | if (current.value === element) { 114 | return index; 115 | } 116 | 117 | current = current.next; 118 | index++; 119 | } 120 | 121 | return -1; 122 | } 123 | 124 | size() { 125 | return this.length; 126 | } 127 | 128 | isEmpty() { 129 | return this.length === 0; 130 | } 131 | 132 | print() { 133 | let current = this.head; 134 | 135 | while(current) { 136 | console.log(current.value); 137 | current = current.next; 138 | } 139 | } 140 | } 141 | 142 | console.log('s01e11 - Linked List'); 143 | 144 | let payload = { a: 4 }; 145 | 146 | function addItems() { 147 | console.log('\n Add Items'); 148 | 149 | list.add( {a: 1} ); 150 | list.add( {a: 2} ); 151 | list.add( {a: 3} ); 152 | 153 | list.insert(2, payload); 154 | 155 | list.insert(0, {a: 5}); 156 | list.insert(5, {a: 6}); 157 | 158 | list.print(); 159 | } 160 | 161 | function getItems() { 162 | console.log('\n Get Items'); 163 | 164 | console.log('get(4):', list.get(4)); 165 | console.log('get(0):', list.get(0)); 166 | console.log('get(-5):', list.get(-5)); 167 | 168 | console.log('indexOf {a: 5}:', list.indexOf({a: 5})); 169 | console.log('indexOf payload:', list.indexOf(payload)); 170 | } 171 | 172 | function removeItems() { 173 | console.log('\n Remove Items'); 174 | 175 | console.log(' Before:'); 176 | list.print(); 177 | 178 | list.remove(payload); 179 | 180 | console.log(' After:'); 181 | list.print(); 182 | } 183 | 184 | 185 | let list = new LinkedList(); 186 | 187 | addItems(); 188 | getItems(); 189 | removeItems(); 190 | -------------------------------------------------------------------------------- /s01e12_Tree/tree.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(value) { 3 | this.value = value; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | } 8 | 9 | class BinarySearchTree { 10 | constructor() { 11 | this.root = null; 12 | } 13 | 14 | add(value) { 15 | this.root = addWithin(this.root, value); 16 | 17 | function addWithin(node, value) { 18 | if (!node) { 19 | return new Node(value); 20 | } 21 | 22 | if (node.value === value) { 23 | return node; 24 | } 25 | 26 | if (value < node.value) { 27 | node.left = addWithin(node.left, value); 28 | } else { 29 | node.right = addWithin(node.right, value); 30 | } 31 | 32 | return node; 33 | } 34 | } 35 | 36 | has(value) { 37 | return searchWithin(this.root, value); 38 | 39 | function searchWithin(node, value) { 40 | if (!node) { 41 | return false; 42 | } 43 | 44 | if (node.value === value) { 45 | return true; 46 | } 47 | 48 | return value < node.value ? 49 | searchWithin(node.left, value) : 50 | searchWithin(node.right, value); 51 | } 52 | } 53 | 54 | remove(value) { 55 | this.root = removeNode(this.root, value); 56 | 57 | function removeNode(node, value) { 58 | if (!node) { 59 | return null; 60 | } 61 | 62 | if (value < node.value) { 63 | node.left = removeNode(node.left, value); 64 | return node; 65 | } else if (node.value < value) { 66 | node.right = removeNode(node.right, value); 67 | return node; 68 | } else { 69 | // equal - should remove this item 70 | if (!node.left && !node.right) { 71 | // put null instead of item 72 | return null; 73 | } 74 | 75 | if (!node.left) { 76 | // set right child instead of item 77 | node = node.right; 78 | return node; 79 | } 80 | 81 | if (!node.right) { 82 | // set left child instead of item 83 | node = node.left; 84 | return node; 85 | } 86 | 87 | // both children exists for this item 88 | let minFromRight = node.right; 89 | while (minFromRight.left) { 90 | minFromRight = minFromRight.left; 91 | } 92 | node.value = minFromRight.value; 93 | 94 | node.right = removeNode(node.right, minFromRight.value); 95 | 96 | return node; 97 | } 98 | } 99 | } 100 | 101 | min() { 102 | if (!this.root) { 103 | return; 104 | } 105 | 106 | let node = this.root; 107 | while (node.left) { 108 | node = node.left; 109 | } 110 | 111 | return node.value; 112 | } 113 | 114 | max() { 115 | if (!this.root) { 116 | return; 117 | } 118 | 119 | let node = this.root; 120 | while (node.right) { 121 | node = node.right; 122 | } 123 | 124 | return node.value; 125 | } 126 | 127 | leftTraverse(cb) { 128 | doLeft(this.root, cb); 129 | 130 | function doLeft(node, cb) { 131 | if (node) { 132 | doLeft(node.left, cb); 133 | cb(node.value); 134 | doLeft(node.right, cb); 135 | } 136 | } 137 | } 138 | 139 | rightTraverse(cb) { 140 | doRight(this.root, cb); 141 | 142 | function doRight(node, cb) { 143 | if (node) { 144 | doRight(node.right, cb); 145 | cb(node.value); 146 | doRight(node.left, cb); 147 | } 148 | } 149 | } 150 | } 151 | 152 | console.log('s01e12 - BST (Binary Search Tree)'); 153 | 154 | function addItems() { 155 | console.log('\n Add Items'); 156 | console.log('add 13, 15, 9, 20, 18, 32, 25'); 157 | 158 | bst.add(13); 159 | bst.add(15); 160 | bst.add(9); 161 | bst.add(20); 162 | bst.add(18); 163 | bst.add(32); 164 | bst.add(25); 165 | 166 | 167 | // Should get something like this: 168 | // 13 169 | // / \ 170 | // 9 15 171 | // \ 172 | // 20 173 | // / \ 174 | // 18 32 175 | // / 176 | // 25 177 | } 178 | 179 | function getItems() { 180 | console.log('\n Get Items'); 181 | 182 | console.log('has 10', bst.has(10)); 183 | console.log('has 15', bst.has(15)); 184 | console.log('\n', bst); 185 | 186 | console.log(' Left Traverse:'); 187 | bst.leftTraverse((val) => console.log(val)); 188 | 189 | console.log(' Right Traverse:'); 190 | bst.rightTraverse((val) => console.log(val)); 191 | 192 | console.log('min:', bst.min()); 193 | console.log('max:', bst.max()); 194 | } 195 | 196 | function removeItem() { 197 | console.log(' Remove Item'); 198 | 199 | bst.remove(15); 200 | console.log('remove 15'); 201 | console.log(bst); 202 | 203 | console.log(' Left Traverse:'); 204 | bst.leftTraverse((val) => console.log(val)); 205 | } 206 | 207 | 208 | const bst = new BinarySearchTree(); 209 | 210 | addItems(); 211 | getItems(); 212 | removeItem(); 213 | --------------------------------------------------------------------------------