diff --git a/.travis.yml b/.travis.yml index 008cbc167..b0e500072 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ language: node_js node_js: - - "5.10.0" + - "12.18.2" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..9c3bb9263 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,154 @@ +{ + "name": "js-training", + "version": "0.9.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", + "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", + "dev": true, + "requires": { + "ms": "0.7.1" + } + }, + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", + "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "dev": true, + "requires": { + "inherits": "2", + "minimatch": "0.3" + } + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", + "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz", + "integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.2.0", + "diff": "1.4.0", + "escape-string-regexp": "1.0.2", + "glob": "3.2.11", + "growl": "1.9.2", + "jade": "0.26.3", + "mkdirp": "0.5.1", + "supports-color": "1.2.0", + "to-iso-string": "0.0.2" + } + }, + "ms": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", + "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "supports-color": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz", + "integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=", + "dev": true + }, + "to-iso-string": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz", + "integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=", + "dev": true + } + } +} diff --git a/package.json b/package.json index 712b264fa..1f387c39b 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "devDependencies": { "mocha": "^2.3.4" }, - "repository" : { - "type" : "git", - "url" : "https://github.com/rolling-scopes-school/js-assignments.git" + "repository": { + "type": "git", + "url": "https://github.com/rolling-scopes-school/js-assignments.git" } } diff --git a/task/06-conditions-n-loops-tasks.js b/task/06-conditions-n-loops-tasks.js index 249194c34..663aee788 100644 --- a/task/06-conditions-n-loops-tasks.js +++ b/task/06-conditions-n-loops-tasks.js @@ -30,7 +30,18 @@ * */ function getFizzBuzz(num) { - throw new Error('Not implemented'); + let result; + + if ((num % 3 === 0) && (num % 5 === 0)) + result = 'FizzBuzz'; + else if (num % 3 === 0) + result = 'Fizz'; + else if (num % 5 === 0) + result = 'Buzz'; + else + result = num; + + return result; } @@ -46,7 +57,12 @@ function getFizzBuzz(num) { * 10 => 3628800 */ function getFactorial(n) { - throw new Error('Not implemented'); + let result = 1; + + for (let i = 1; i <= n; i++) + result *= i; + + return result; } @@ -63,7 +79,12 @@ function getFactorial(n) { * -1,1 => 0 ( = -1 + 0 + 1 ) */ function getSumBetweenNumbers(n1, n2) { - throw new Error('Not implemented'); + let result = 0; + + for (let i = n1; i <= n2; i++) + result = result + i + + return result; } @@ -82,7 +103,7 @@ function getSumBetweenNumbers(n1, n2) { * 10,10,10 => true */ function isTriangle(a,b,c) { - throw new Error('Not implemented'); + return ((a < b+c) && (b < a+c) && (c < a+b)) ? true : false } @@ -119,7 +140,12 @@ function isTriangle(a,b,c) { * */ function doRectanglesOverlap(rect1, rect2) { - throw new Error('Not implemented'); + let aLeftOfB = rect1.left + rect1.width < rect2.left; + let aRightOfB = rect1.left > rect2.left + rect2.width; + let aAboveB = rect1.top > rect2.top + rect2.height; + let aBelowB = rect1.top + rect1.height < rect2.top; + + return !( aLeftOfB || aRightOfB || aAboveB || aBelowB ); } @@ -150,7 +176,7 @@ function doRectanglesOverlap(rect1, rect2) { * */ function isInsideCircle(circle, point) { - throw new Error('Not implemented'); + return ((point.x - circle.center.x) ** 2 + (point.y - circle.center.y) ** 2 <= (circle.radius - 0.00001) ** 2); } @@ -166,7 +192,30 @@ function isInsideCircle(circle, point) { * 'entente' => null */ function findFirstSingleChar(str) { - throw new Error('Not implemented'); + let searchChar; + let result = null; + let newStr = null; + + OUTER_LOOP: for (let i = 0; i < str.length; i++) + { + searchChar = str[i]; + newStr = str.replace(searchChar, ''); + + INNER_LOOP: for (let j = 0; j < newStr.length; j++) + { + if (searchChar == newStr[j]) + { + break INNER_LOOP; + } + if (j + 1 == newStr.length) + { + result = searchChar; + break OUTER_LOOP; + } + } + } + + return result; } @@ -192,7 +241,27 @@ function findFirstSingleChar(str) { * */ function getIntervalString(a, b, isStartIncluded, isEndIncluded) { - throw new Error('Not implemented'); + + let firstBracket; + let secondBracket; + let firstNum; + let secondNum; + + firstBracket = isStartIncluded ? "[" : "("; + secondBracket = isEndIncluded ? "]" : ")"; + + if (a < b) + { + firstNum = a; + secondNum = b; + } + else + { + firstNum = b; + secondNum = a; + } + + return firstBracket + firstNum + ', ' + secondNum + secondBracket; } @@ -209,7 +278,15 @@ function getIntervalString(a, b, isStartIncluded, isEndIncluded) { * 'noon' => 'noon' */ function reverseString(str) { - throw new Error('Not implemented'); + + let newStr = ''; + + for (let i = str.length-1; i >= 0; i--) + { + newStr = newStr + str[i]; + } + + return newStr; } @@ -226,7 +303,17 @@ function reverseString(str) { * 34143 => 34143 */ function reverseInteger(num) { - throw new Error('Not implemented'); + + let chooseNum; + let newNum = ''; + + for (let i = 0; i < num.toString().length; i++) + { + chooseNum = Math.floor(num % (10 * (10 ** i))/ (1 * (10 ** i))); + newNum = newNum + chooseNum; + } + + return newNum; } @@ -250,8 +337,26 @@ function reverseInteger(num) { * 5436468789016589 => false * 4916123456789012 => false */ + function isCreditCardNumber(ccn) { - throw new Error('Not implemented'); + + let sum = 0; + let evenChar = false; + let number; + + for (let i = ccn.toString().length - 1; i >= 0; i--) + { + number = parseInt(ccn.toString().charAt(i), 10); + + if (evenChar && (number *= 2) > 9) + { + number -= 9; + } + sum += number; + evenChar = !evenChar; + } + + return (sum % 10) == 0; } @@ -270,7 +375,28 @@ function isCreditCardNumber(ccn) { * 165536 (1+6+5+5+3+6 = 26, 2+6 = 8) => 8 */ function getDigitalRoot(num) { - throw new Error('Not implemented'); + + let newNum = num; + let sum = 0; + + while (newNum.toString().length !== 1) + { + sum += newNum % 10; + newNum = (newNum - newNum % 10) / 10; + + if (newNum.toString().length === 1) + { + sum += newNum; + + if (sum > 9) + { + newNum = sum; + sum = 0; + } + } + } + + return sum; } @@ -296,7 +422,28 @@ function getDigitalRoot(num) { * '{[(<{[]}>)]}' = true */ function isBracketsBalanced(str) { - throw new Error('Not implemented'); + let chars = str.split(''); + let stack = []; + let open = ['{', '(', '[', '<']; + let close = ['}', ')', ']', '>']; + let closeIndex; + let openIndex; + + for (let i = 0; i < chars.length; i++) + { + openIndex = open.indexOf(chars[i]); + if (openIndex !== -1) stack.push(openIndex); + closeIndex = close.indexOf(chars[i]); + if (closeIndex !== -1) + { + openIndex = stack.pop(); + if (closeIndex !== openIndex) return false; + } + } + + if (stack.length !== 0) return false; + + return true; } @@ -332,7 +479,69 @@ function isBracketsBalanced(str) { * */ function timespanToHumanString(startDate, endDate) { - throw new Error('Not implemented'); + + let dateDif = endDate - startDate; + let message = ""; + + switch(true) { + case dateDif / 8.64e7 > 546: + { + message = (Math.round(dateDif / 3.1536e10) + " years ago"); + break; + } + case ((dateDif / 8.64e7) > 345) && ((dateDif / 8.64e7) <= 546): + { + message = "a year ago"; + break; + } + case ((dateDif / 8.64e7) > 45) && ((dateDif / 8.64e7) <= 345): + { + message = (Math.round(dateDif / 2.592e9) + " months ago"); + break; + } + case ((dateDif / 8.64e7) > 25) && ((dateDif / 8.64e7) <= 45): + { + message = "a month ago"; + break; + } + case ((dateDif / 3.6e6) > 36) && ((dateDif / 8.64e7) <= 25): + { + message = (Math.round((dateDif-1) / 8.64e7) + " days ago"); + break; + } + case ((dateDif / 3.6e6) > 22) && ((dateDif / 3.6e6) <= 36): + { + message = "a day ago"; + break; + } + case ((dateDif / 6e4) > 90) && ((dateDif / 3.6e6) <= 22): + { + message = (Math.round((dateDif-1) / 3.6e6) + " hours ago"); + break; + } + case ((dateDif / 6e4) > 45) && ((dateDif / 6e4) <= 90): + { + message = "an hour ago"; + break; + } + case ((dateDif / 1e3) > 90) && ((dateDif / 6e4) <= 45): + { + message = (Math.round((dateDif-1) / 6e4) + " minutes ago"); + break; + } + case ((dateDif / 1e3) > 45) && ((dateDif / 1e3) <= 90): + { + message = "a minute ago"; + break; + } + case (dateDif > 0) && ((dateDif / 1e3) <= 45): + { + message = "a few seconds ago"; + break; + } + } + + return message; } @@ -356,7 +565,7 @@ function timespanToHumanString(startDate, endDate) { * 365, 10 => '365' */ function toNaryString(num, n) { - throw new Error('Not implemented'); + return num.toString(n); } @@ -373,7 +582,44 @@ function toNaryString(num, n) { * ['/web/favicon.ico', '/web-scripts/dump', '/webalizer/logs'] => '/' */ function getCommonDirectoryPath(pathes) { - throw new Error('Not implemented'); + + let str = ''; + let arrLen = pathes.length; + let arr1; + let arr2; + let arr3; + + switch(arrLen) + { + case 2: + { + arr1 = pathes[0].split('/'); + arr2 = pathes[1].split('/'); + + for (let i = 0; i < arr1.length; i++) + { + if (arr1[i] == arr2[i]) + str += arr1[i] + '/'; + } + break; + } + case 3: + { + arr1 = pathes[0].split('/'); + arr2 = pathes[1].split('/'); + arr3 = pathes[2].split('/'); + + for (let i = 0; i < arr1.length; i++) + { + if ((arr1[i] == arr2[i]) && (arr2[i] == arr3[i])) + { + str += arr1[i] + '/'; + } + } + break; + } + } + return str; } @@ -396,10 +642,30 @@ function getCommonDirectoryPath(pathes) { * */ function getMatrixProduct(m1, m2) { - throw new Error('Not implemented'); + + let result = []; + let sum = 0; + + for(let j = 0; j < m1.length; j++) + { + result[j] = []; + for (let k = 0; k < m2[0].length; k++) + { + sum = 0; + for(let i = 0; i < m2.length; i++) + { + sum += m2[i][k] * m1[j][i]; + } + result[j].push(sum); + } + } + + return result; } + + /** * Returns the evaluation of the specified tic-tac-toe position. * See the details: https://en.wikipedia.org/wiki/Tic-tac-toe @@ -431,7 +697,49 @@ function getMatrixProduct(m1, m2) { * */ function evaluateTicTacToePosition(position) { - throw new Error('Not implemented'); + + function comparison(arr1, arr2) + { + return JSON.stringify(arr1) == JSON.stringify(arr2); + } + + let xArr = ['X', 'X', 'X']; + let oArr = ['0', '0', '0']; + let colArr = []; + let mainDiarArr = []; + let sideDiarArr = []; + let result = undefined; + + for (let i = 0; i < position.length; i++) + { + + colArr.splice(0, colArr.length) + + for (let j = 0; j < position[i].length; j++) + { + colArr.push(position[j][i]); + + if (i == j) + mainDiarArr[i] = position[i][j]; + + if (i + j == position.length - 1) + sideDiarArr[position.length - 1 - j] = position[i][j]; + } + + if (comparison(position[i], xArr) || comparison(colArr, xArr) || comparison(mainDiarArr, xArr) || comparison(sideDiarArr, xArr)) + { + result = 'X'; + break; + } + + if (comparison(position[i], oArr) || comparison(colArr, oArr) || comparison(mainDiarArr, oArr) || comparison(sideDiarArr, oArr)) + { + result = '0'; + break; + } + } + + return result; }