diff --git a/task/01-strings-tasks.js b/task/01-strings-tasks.js index e28054657..efd027d78 100644 --- a/task/01-strings-tasks.js +++ b/task/01-strings-tasks.js @@ -4,7 +4,7 @@ * * * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String * - * * + * npm test ./test/01-strings-tests.js * ********************************************************************************************/ @@ -22,7 +22,7 @@ * '', 'bb' => 'bb' */ function concatenateStrings(value1, value2) { - throw new Error('Not implemented'); + return value1 + value2; } @@ -38,7 +38,7 @@ function concatenateStrings(value1, value2) { * '' => 0 */ function getStringLength(value) { - throw new Error('Not implemented'); + return value.length; } /** @@ -55,7 +55,7 @@ function getStringLength(value) { * 'Chuck','Norris' => 'Hello, Chuck Norris!' */ function getStringFromTemplate(firstName, lastName) { - throw new Error('Not implemented'); + return "Hello, " + firstName + " " + lastName + "!"; } /** @@ -69,10 +69,9 @@ function getStringFromTemplate(firstName, lastName) { * 'Hello, Chuck Norris!' => 'Chuck Norris' */ function extractNameFromTemplate(value) { - throw new Error('Not implemented'); + return value.slice(7, -1); } - /** * Returns a first char of the given string. * @@ -84,7 +83,7 @@ function extractNameFromTemplate(value) { * 'cat' => 'c' */ function getFirstChar(value) { - throw new Error('Not implemented'); + return value[0]; } /** @@ -99,7 +98,7 @@ function getFirstChar(value) { * '\tHello, World! ' => 'Hello, World!' */ function removeLeadingAndTrailingWhitespaces(value) { - throw new Error('Not implemented'); + return value.trim(); } /** @@ -114,7 +113,7 @@ function removeLeadingAndTrailingWhitespaces(value) { * 'cat', 3 => 'catcatcat' */ function repeatString(value, count) { - throw new Error('Not implemented'); + return value.repeat(count); } /** @@ -130,7 +129,7 @@ function repeatString(value, count) { * 'ABABAB','BA' => 'ABAB' */ function removeFirstOccurrences(str, value) { - throw new Error('Not implemented'); + return str.replace(value,''); } /** @@ -145,7 +144,7 @@ function removeFirstOccurrences(str, value) { * '' => 'a' */ function unbracketTag(str) { - throw new Error('Not implemented'); + return str.replace(/[<,>]/gi,''); } @@ -160,7 +159,7 @@ function unbracketTag(str) { * 'abcdefghijklmnopqrstuvwxyz' => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' */ function convertToUpperCase(str) { - throw new Error('Not implemented'); + return str.toUpperCase(); } /** @@ -174,7 +173,8 @@ function convertToUpperCase(str) { * 'info@gmail.com' => ['info@gmail.com'] */ function extractEmails(str) { - throw new Error('Not implemented'); + let arr = str.split(';') + return arr; } /** @@ -201,7 +201,10 @@ function extractEmails(str) { * */ function getRectangleString(width, height) { - throw new Error('Not implemented'); + let top = `┌${'─'.repeat(width - 2)}┐\n`; + let mid = `│${' '.repeat(width - 2)}│\n`; + let bottom = `└${'─'.repeat(width - 2)}┘\n`; + return top + mid.repeat(height - 2) + bottom; } @@ -221,7 +224,9 @@ function getRectangleString(width, height) { * */ function encodeToRot13(str) { - throw new Error('Not implemented'); + const originalAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + const cipher = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM" + return str.replace(/[a-z]/gi, letter => cipher[originalAlpha.indexOf(letter)]) } /** @@ -238,7 +243,7 @@ function encodeToRot13(str) { * isString(new String('test')) => true */ function isString(value) { - throw new Error('Not implemented'); + return Object.prototype.toString.call(value) === "[object String]" } @@ -267,7 +272,14 @@ function isString(value) { * 'K♠' => 51 */ function getCardId(value) { - throw new Error('Not implemented'); + const cards = [ + 'A♣', '2♣', '3♣', '4♣', '5♣', '6♣', '7♣', '8♣', '9♣', '10♣', 'J♣', 'Q♣', 'K♣', + 'A♦', '2♦', '3♦', '4♦', '5♦', '6♦', '7♦', '8♦', '9♦', '10♦', 'J♦', 'Q♦', 'K♦', + 'A♥', '2♥', '3♥', '4♥', '5♥', '6♥', '7♥', '8♥', '9♥', '10♥', 'J♥', 'Q♥', 'K♥', + 'A♠', '2♠', '3♠', '4♠', '5♠', '6♠', '7♠', '8♠', '9♠', '10♠', 'J♠', 'Q♠', 'K♠', + ]; + + return cards.indexOf(value); } diff --git a/task/02-numbers-tasks.js b/task/02-numbers-tasks.js index c9ed20208..d081441fd 100644 --- a/task/02-numbers-tasks.js +++ b/task/02-numbers-tasks.js @@ -6,7 +6,7 @@ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math * - * * + * npm test ./test/02-numbers-tests.js * ********************************************************************************************/ @@ -22,7 +22,7 @@ * 5, 5 => 25 */ function getRectangleArea(width, height) { - throw new Error('Not implemented'); + return width*height; } @@ -38,7 +38,7 @@ function getRectangleArea(width, height) { * 0 => 0 */ function getCicleCircumference(radius) { - throw new Error('Not implemented'); + return 2 * Math.PI * radius; } /** @@ -54,7 +54,11 @@ function getCicleCircumference(radius) { * -3, 3 => 0 */ function getAverage(value1, value2) { - throw new Error('Not implemented'); + /*let a=Number(value1); + let b=Number(value2); + let res = (a+b)/2; + return res;*/ + return value1/2 + value2/2; } /** @@ -73,7 +77,8 @@ function getAverage(value1, value2) { * (-5,0) (10,-10) => 18.027756377319946 */ function getDistanceBetweenPoints(x1, y1, x2, y2) { - throw new Error('Not implemented'); + let sum = Math.pow(x1-x2, 2)+Math.pow(y1-y2, 2); + return Math.pow(sum, 0.5); } /** @@ -89,7 +94,8 @@ function getDistanceBetweenPoints(x1, y1, x2, y2) { * 5*x = 0 => 0 */ function getLinearEquationRoot(a, b) { - throw new Error('Not implemented'); + let x= (0-b)/a; + return x; } @@ -111,7 +117,11 @@ function getLinearEquationRoot(a, b) { * (0,1) (1,2) => 0 */ function getAngleBetweenVectors(x1, y1, x2, y2) { - throw new Error('Not implemented'); + var angle = Math.atan2(y2, x2) - Math.atan2(y1, x1) + if (angle < 0) { + angle += 2 * Math.PI; + } + return angle } /** @@ -127,7 +137,7 @@ function getAngleBetweenVectors(x1, y1, x2, y2) { * 0 => 0 */ function getLastDigit(value) { - throw new Error('Not implemented'); + return value%10; } @@ -143,7 +153,7 @@ function getLastDigit(value) { * '-525.5' => -525.5 */ function parseNumberFromString(value) { - throw new Error('Not implemented'); + return Number(value); } /** @@ -160,7 +170,9 @@ function parseNumberFromString(value) { * 1,2,3 => 3.741657386773941 */ function getParallelipidedDiagonal(a,b,c) { - throw new Error('Not implemented'); + let sum = Math.pow(a,2)+Math.pow(b,2)+Math.pow(c,2); + let result=Math.pow(sum,0.5); + return result; } /** @@ -181,7 +193,10 @@ function getParallelipidedDiagonal(a,b,c) { * 1678, 3 => 2000 */ function roundToPowerOfTen(num, pow) { - throw new Error('Not implemented'); + let a = Math.pow(10,pow); + let b = num/a; + let c = Math.round(b); + return c*a; } /** @@ -202,7 +217,12 @@ function roundToPowerOfTen(num, pow) { * 17 => true */ function isPrime(n) { - throw new Error('Not implemented'); + for(let i=2; i 42 */ function toNumber(value, def) { - throw new Error('Not implemented'); + const num = Number(value); + if(isNaN(num)){ + return def; + }else{ + return num; + } } module.exports = { diff --git a/task/03-date-tasks.js b/task/03-date-tasks.js index 83c6266bc..89f1a8dce 100644 --- a/task/03-date-tasks.js +++ b/task/03-date-tasks.js @@ -5,7 +5,7 @@ * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates#Date_object * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date * - * * + * npm test ./test/03-date-tests.js * ********************************************************************************************/ @@ -22,7 +22,7 @@ * 'Sun, 17 May 1998 03:00:00 GMT+01' => Date() */ function parseDataFromRfc2822(value) { - throw new Error('Not implemented'); + return Date.parse(value); } /** @@ -37,7 +37,7 @@ function parseDataFromRfc2822(value) { * '2016-01-19T08:07:37Z' => Date() */ function parseDataFromIso8601(value) { - throw new Error('Not implemented'); + return Date.parse(value); } @@ -56,7 +56,8 @@ function parseDataFromIso8601(value) { * Date(2015,1,1) => false */ function isLeapYear(date) { - throw new Error('Not implemented'); + let year = date.getFullYear(); + return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0); } @@ -76,7 +77,7 @@ function isLeapYear(date) { * Date(2000,1,1,10,0,0), Date(2000,1,1,15,20,10,453) => "05:20:10.453" */ function timeSpanToString(startDate, endDate) { - throw new Error('Not implemented'); + return (new Date(endDate - startDate)).toISOString().slice(11, -1); } @@ -94,7 +95,13 @@ function timeSpanToString(startDate, endDate) { * Date.UTC(2016,3,5,21, 0) => Math.PI/2 */ function angleBetweenClockHands(date) { - throw new Error('Not implemented'); + const hoursArrow = 0.5 * (60 * (date.getUTCHours() % 12) + date.getUTCMinutes()); + const minutesArrow = 6 * date.getUTCMinutes(); + let angle = Math.abs(hoursArrow - minutesArrow); + if (angle > 180) { + angle = 360 - angle; + } + return (angle * Math.PI / 180); } diff --git a/task/04-arrays-tasks.js b/task/04-arrays-tasks.js index ff3a4c019..9e95dad71 100644 --- a/task/04-arrays-tasks.js +++ b/task/04-arrays-tasks.js @@ -6,7 +6,7 @@ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array * * * * NOTE : Please do not use loops! All tasks can be implmeneted using standard Array methods * - * * + * npm test ./test/04-arrays-tests.js * *********************************************************************************************/ @@ -23,7 +23,7 @@ * [0, 1, 2, 3, 4, 5], 5 => 5 */ function findElement(arr, value) { - throw new Error('Not implemented'); + return arr.indexOf(value); } /** @@ -38,7 +38,11 @@ function findElement(arr, value) { * 5 => [ 1, 3, 5, 7, 9 ] */ function generateOdds(len) { - throw new Error('Not implemented'); + function iter(n, current, acc) { + if (n == len) return acc; + return iter(n + 1, current + 2, acc.concat(current)) + } + return iter(0, 1, []); } @@ -54,7 +58,10 @@ function generateOdds(len) { * [] => [] */ function doubleArray(arr) { - throw new Error('Not implemented'); + let array1 = arr; + let array2 = arr; + let array3 = array1.concat(array2); + return array3; } @@ -70,7 +77,9 @@ function doubleArray(arr) { * [] => [] */ function getArrayOfPositives(arr) { - throw new Error('Not implemented'); + return arr.filter(function(value) { + return value > 0; + }); } /** @@ -85,7 +94,7 @@ function getArrayOfPositives(arr) { * [ 'cat, 'dog', 'raccon' ] => [ 'cat', 'dog', 'racoon' ] */ function getArrayOfStrings(arr) { - throw new Error('Not implemented'); + return arr.filter((x) => typeof (x) === 'string'); } /** @@ -102,7 +111,9 @@ function getArrayOfStrings(arr) { * [ false, 0, NaN, '', undefined ] => [ ] */ function removeFalsyValues(arr) { - throw new Error('Not implemented'); + return arr.filter(function(value) { + return Boolean(value); + }); } /** @@ -116,7 +127,7 @@ function removeFalsyValues(arr) { * [ 'a', 'b', 'c', 'd', 'e', 'f', 'g' ] => [ 'A', 'B', 'C', 'D', 'E', 'F', 'G' ] */ function getUpperCaseStrings(arr) { - throw new Error('Not implemented'); + return arr.map(value=>value.toUpperCase()); } @@ -131,7 +142,7 @@ function getUpperCaseStrings(arr) { * [ 'angular', 'react', 'ember' ] => [ 7, 5, 5 ] */ function getStringsLength(arr) { - throw new Error('Not implemented'); + return arr.map(value=>value.length); } /** @@ -146,7 +157,7 @@ function getStringsLength(arr) { * [ 1, 'b', 'c'], 0, 'x' => [ 'x', 1, 'b', 'c' ] */ function insertItem(arr, item, index) { - throw new Error('Not implemented'); + return arr.splice(index,0,item); } /** @@ -160,7 +171,7 @@ function insertItem(arr, item, index) { * [ 'a', 'b', 'c', 'd'], 3 => [ 'a', 'b', 'c' ] */ function getHead(arr, n) { - throw new Error('Not implemented'); + return arr.splice(0,n); } @@ -175,7 +186,7 @@ function getHead(arr, n) { * [ 'a', 'b', 'c', 'd'], 3 => [ 'b', 'c', 'd' ] */ function getTail(arr, n) { - throw new Error('Not implemented'); + return arr.slice(Math.max(arr.length - n, 1)); } @@ -200,7 +211,7 @@ function getTail(arr, n) { * +'30,31,32,33,34' */ function toCsvText(arr) { - throw new Error('Not implemented'); + return arr.join('\n'); } /** @@ -215,7 +226,7 @@ function toCsvText(arr) { * [ 10, 100, -1 ] => [ 100, 10000, 1 ] */ function toArrayOfSquares(arr) { - throw new Error('Not implemented'); + return arr.map(value => value*value); } @@ -234,7 +245,7 @@ function toArrayOfSquares(arr) { * [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] => [ 1, 3, 6, 10, 15, 21, 28, 36, 45, 55 ] */ function getMovingSum(arr) { - throw new Error('Not implemented'); + return arr.map((x, y, arr) => arr.slice(0, y + 1).reduce((fs, val) => fs + val)); } /** @@ -249,7 +260,7 @@ function getMovingSum(arr) { * [ "a" ] => [] */ function getSecondItems(arr) { - throw new Error('Not implemented'); + return arr.filter((x, y) => y % 2 === 1); } @@ -268,7 +279,12 @@ function getSecondItems(arr) { * [ 1,2,3,4,5 ] => [ 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5 ] */ function propagateItemsByPositionIndex(arr) { - throw new Error('Not implemented'); + let newArray = []; + arr.map((x, y) => { + newArray = newArray.concat(new Array(y + 1).fill(x)); + return x; + }); + return newArray; } @@ -286,7 +302,8 @@ function propagateItemsByPositionIndex(arr) { * [ 10, 10, 10, 10 ] => [ 10, 10, 10 ] */ function get3TopItems(arr) { - throw new Error('Not implemented'); + arr.sort(function(a, b){return b-a}); + return arr.slice(0,3); } @@ -304,7 +321,7 @@ function get3TopItems(arr) { * [ 1, '2' ] => 1 */ function getPositivesCount(arr) { - throw new Error('Not implemented'); + return arr.filter((x) => (x > 0) && (Number(x) === x)).length; } /** @@ -321,7 +338,14 @@ function getPositivesCount(arr) { * [ 'one','one','one','zero' ] => [ 'zero','one','one','one' ] */ function sortDigitNamesByNumericOrder(arr) { - throw new Error('Not implemented'); + const digitsComparator = (a, b) => { + const mapper = ['zero', 'one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', 'nine'] + return mapper.indexOf(a) - mapper.indexOf(b) + } + + const res = arr.sort(digitsComparator); + return res; } /** @@ -337,7 +361,7 @@ function sortDigitNamesByNumericOrder(arr) { * [ 1, 10, 100, 1000 ] => 1111 */ function getItemsSum(arr) { - throw new Error('Not implemented'); + return arr.reduce((a, b) => a + b, 0); } /** @@ -353,7 +377,7 @@ function getItemsSum(arr) { * [ null, undefined, NaN, false, 0, '' ] => 6 */ function getFalsyValuesCount(arr) { - throw new Error('Not implemented'); + return arr.filter((x) => !x).length; } /** @@ -371,7 +395,7 @@ function getFalsyValuesCount(arr) { * [ true, 0, 1, 'true' ], true => 1 */ function findAllOccurences(arr, item) { - throw new Error('Not implemented'); + return arr.reduce(function(n, value) {return n + (value === item);}, 0); } /** @@ -386,7 +410,7 @@ function findAllOccurences(arr, item) { * ['rock', 'paper', 'scissors'] => 'rock,paper,scissors' */ function toStringList(arr) { - throw new Error('Not implemented'); + return arr.join(','); } @@ -415,7 +439,18 @@ function toStringList(arr) { * { country: 'Russia', city: 'Saint Petersburg' } */ function sortCitiesArray(arr) { - throw new Error('Not implemented'); + return arr.sort((a, b) => { + if (a.country > b.country) { + return 1; + } + if (a.country < b.country) { + return -1; + } + if (a.city > b.city) { + return 1; + } + return -1; + }); } /** @@ -437,7 +472,12 @@ function sortCitiesArray(arr) { * [0,0,0,0,1]] */ function getIdentityMatrix(n) { - throw new Error('Not implemented'); + return new Array(n).fill(0).map((x, y) => new Array(n).fill(0).map((x, y_) => { + if (y === y_) { + return 1; + } + return 0; + })); } /** @@ -454,7 +494,7 @@ function getIdentityMatrix(n) { * 3, 3 => [ 3 ] */ function getIntervalArray(start, end) { - throw new Error('Not implemented'); + return Array(end - start + 1).fill().map((x, y) => start + y); } /** @@ -469,7 +509,7 @@ function getIntervalArray(start, end) { * [ 1, 1, 2, 2, 3, 3, 4, 4] => [ 1, 2, 3, 4] */ function distinct(arr) { - throw new Error('Not implemented'); + return arr.filter((x, y) => arr.indexOf(x) === y); } /** @@ -503,7 +543,18 @@ function distinct(arr) { * } */ function group(array, keySelector, valueSelector) { - throw new Error('Not implemented'); + const map = new Map(); + array.map((x) => [keySelector(x), valueSelector(x)]).map((x) => { + if (map.has(x[0])) { + map.set(x[0], map.get(x[0]).concat(x[1])); + } else { + const arr = Array(1); + arr[0] = x[1]; + map.set(x[0], arr); + } + return x; + }); + return map; } @@ -519,7 +570,9 @@ function group(array, keySelector, valueSelector) { * ['one','two','three'], x=>x.split('') => ['o','n','e','t','w','o','t','h','r','e','e'] */ function selectMany(arr, childrenSelector) { - throw new Error('Not implemented'); + let retArr = []; + arr.map(childrenSelector).map((x) => retArr = retArr.concat(x)); + return retArr; } @@ -536,7 +589,7 @@ function selectMany(arr, childrenSelector) { * [[[ 1, 2, 3]]], [ 0, 0, 1 ] => 2 (arr[0][0][1]) */ function getElementByIndexes(arr, indexes) { - throw new Error('Not implemented'); + return arr.join().split(',')[indexes.reduce((accumulator, value) => accumulator + value)]; } @@ -559,7 +612,19 @@ function getElementByIndexes(arr, indexes) { * */ function swapHeadAndTail(arr) { - throw new Error('Not implemented'); + let mid = Math.floor(arr.length / 2); + if((arr.length-(mid*2))!=0){ + let arrMid=arr[mid]; + let head = arr.slice(0, mid); + let tail = arr.slice(mid+1); + let newArr=[]; + return newArr.concat(tail, arrMid, head); + }else{ + let head = arr.slice(0, mid); + let tail = arr.slice(mid); + let newArr=[]; + return newArr.concat(tail, head); + } } diff --git a/task/05-regex-tasks.js b/task/05-regex-tasks.js index b1c60f2d4..d2cdba651 100644 --- a/task/05-regex-tasks.js +++ b/task/05-regex-tasks.js @@ -4,7 +4,7 @@ * * * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions * - * * + * npm test ./test/05-regex-tests.js * ********************************************************************************************/ @@ -31,7 +31,8 @@ * @return {RegExp} */ function getRegexForGuid() { - throw new Error('Not implemented'); + let reg = '[0-9a-f]'; + return new RegExp('^{'+reg+'{8}-'+reg+'{4}-'+reg+'{4}-'+reg+'{4}-'+reg+'{12}}$', 'i'); } @@ -53,7 +54,7 @@ function getRegexForGuid() { * */ function getRegexForPitSpot() { - throw new Error('Not implemented'); + return new RegExp(/.*p.t.*/); } @@ -72,7 +73,7 @@ function getRegexForPitSpot() { * @return {RegExp} */ function getRegexForIPv4() { - throw new Error('Not implemented'); + return /^(([0-2][0-9]{2}|[0-9]{1,2})\.){3}([0-2][0-9]{2}|[0-9]{1,2})$/; } @@ -91,7 +92,7 @@ function getRegexForIPv4() { * @return {RegExp} */ function getRegexForSSN() { - throw new Error('Not implemented'); + return /\d{2}[1-9]-\d{1}[1-9]-\d{3}[1-9]/; } @@ -116,7 +117,7 @@ function getRegexForSSN() { * 'Pa55'.match(validator) => false */ function getPasswordValidator(minLength) { - throw new Error('Not implemented'); + return new RegExp('^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[A-Za-z\\d]{'+minLength+',}'); } diff --git a/task/06-conditions-n-loops-tasks.js b/task/06-conditions-n-loops-tasks.js index 249194c34..2a652a26a 100644 --- a/task/06-conditions-n-loops-tasks.js +++ b/task/06-conditions-n-loops-tasks.js @@ -5,7 +5,7 @@ * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration * - * * + * npm test ./test/06-conditions-n-loops-tests.js * **************************************************************************************************/ @@ -30,7 +30,14 @@ * */ function getFizzBuzz(num) { - throw new Error('Not implemented'); + if((num % 3 === 0) && (num % 5 === 0)) { + return 'FizzBuzz'; + } else if(num % 5 === 0) { + return'Buzz'; + } else if (num % 3 === 0) { + return 'Fizz'; + } + return num; } @@ -46,7 +53,13 @@ function getFizzBuzz(num) { * 10 => 3628800 */ function getFactorial(n) { - throw new Error('Not implemented'); + if (n < 0) { + return -1; + }else if (n === 0){ + return 1; + }else { + return (n * getFactorial(n - 1)); + } } @@ -63,7 +76,11 @@ function getFactorial(n) { * -1,1 => 0 ( = -1 + 0 + 1 ) */ function getSumBetweenNumbers(n1, n2) { - throw new Error('Not implemented'); + let count = 0; + for(let i = n1; i <=n2; i++ ) { + count +=i; + } + return count; } @@ -82,7 +99,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; } @@ -119,7 +136,12 @@ function isTriangle(a,b,c) { * */ function doRectanglesOverlap(rect1, rect2) { - throw new Error('Not implemented'); + return !( + rect1.left + rect1.width < rect2.left || + rect2.left + rect2.width < rect1.left || + rect1.top + rect1.height < rect2.top || + rect2.top + rect2.height < rect1.top + ); } @@ -150,7 +172,9 @@ function doRectanglesOverlap(rect1, rect2) { * */ function isInsideCircle(circle, point) { - throw new Error('Not implemented'); + let dx = point.x - circle.center.x; + let dy = point.y - circle.center.y; + return (dx*dx + dy*dy) < (circle.radius * circle.radius); } @@ -166,7 +190,12 @@ function isInsideCircle(circle, point) { * 'entente' => null */ function findFirstSingleChar(str) { - throw new Error('Not implemented'); + for (let i = 0; i < str.length; i++) { + if (str.indexOf(str[i]) == str.lastIndexOf(str[i])) { + return str[i]; + } + } + return null; } @@ -192,7 +221,11 @@ function findFirstSingleChar(str) { * */ function getIntervalString(a, b, isStartIncluded, isEndIncluded) { - throw new Error('Not implemented'); + let res = ""; + res += (isStartIncluded && res.length === 0) ? "[" : "("; + res += a <= b ? `${a}, ${b}` : `${b}, ${a}`; + res += isEndIncluded ? "]" : ")"; + return res; } @@ -209,7 +242,7 @@ function getIntervalString(a, b, isStartIncluded, isEndIncluded) { * 'noon' => 'noon' */ function reverseString(str) { - throw new Error('Not implemented'); + return [...str].reverse().join(''); } @@ -226,7 +259,9 @@ function reverseString(str) { * 34143 => 34143 */ function reverseInteger(num) { - throw new Error('Not implemented'); + let str = ''; + str += num; + return [...str].reverse().join(''); } @@ -251,7 +286,17 @@ function reverseInteger(num) { * 4916123456789012 => false */ function isCreditCardNumber(ccn) { - throw new Error('Not implemented'); + ccn = [...String(ccn)].reverse(); + ccn = ccn.reduce(function(sum, val, ind) + { + let dig = Number(val); + if(ind % 2) + dig *= 2; + sum += Math.floor(dig / 10); + sum += dig % 10; + return sum; + }, 0); + return (ccn * 3) % 10 == 0; } @@ -270,7 +315,15 @@ function isCreditCardNumber(ccn) { * 165536 (1+6+5+5+3+6 = 26, 2+6 = 8) => 8 */ function getDigitalRoot(num) { - throw new Error('Not implemented'); + do{ + let sum = 0; + while(num > 0){ + sum += num % 10; + num = Math.floor(num / 10); + } + num = sum; + }while(num > 9); + return num; } @@ -296,7 +349,26 @@ function getDigitalRoot(num) { * '{[(<{[]}>)]}' = true */ function isBracketsBalanced(str) { - throw new Error('Not implemented'); + let pair = { + '>': '<', + ')': '(', + ']': '[', + '}': '{' + } + let res = [...str].reduce(function(acc, x, ind) + { + if (['(', '{', '[', '<'].indexOf(x) != -1) + acc.push(x); + else + { + if (acc.length > 0 && acc[acc.length - 1] == pair[x]) + acc.pop(); + else + acc.push(x); + } + return acc; + }, []); + return res.length == 0; } @@ -332,7 +404,74 @@ function isBracketsBalanced(str) { * */ function timespanToHumanString(startDate, endDate) { - throw new Error('Not implemented'); + const diff = (endDate - startDate) / 1000; + const minute = 60; + const hour = minute * 60; + const day = hour * 24; + const month = day * 30; + const year = day * 365; + + if (diff <= 45) + { + return "a few seconds ago"; + } + else if (diff <= 90) + { + return "a minute ago"; + } + else if (diff <= minute * 45) + { + let x=diff%minute; + if(x !== 30) + return `${Math.round(diff / minute)} minutes ago`; + else + return `${Math.floor(diff / minute)} minutes ago`; + } + else if (diff <= minute * 90) + { + return "an hour ago"; + } + else if (diff <= hour * 22) + { + let x=diff%hour; + if(x !== (30*60)) + return `${Math.round(diff / hour)} hours ago`; + else + return `${Math.floor(diff / hour)} hours ago`; + } + else if (diff <= day * 1.5) + { + return "a day ago"; + } + else if (diff <= day * 25) + { + let x=diff%day; + if(x !== (12*60*60)) + return `${Math.round(diff / day)} days ago`; + else + return `${Math.floor(diff / day)} days ago`; + + } + else if (diff <= day * 45) + { + return "a month ago"; + } + else if (diff <= day * 345) + { + let x=diff%(day*365); + if(x !== (15*24*60*60)) + return `${Math.round(diff / month)} months ago`; + else + return `${Math.floor(diff / month)} months ago`; + } + else if (diff <= day * 545) + { + return "a year ago"; + } + else + { + return `${Math.round(diff / year)} years ago`; + } } @@ -356,7 +495,7 @@ function timespanToHumanString(startDate, endDate) { * 365, 10 => '365' */ function toNaryString(num, n) { - throw new Error('Not implemented'); + return num.toString(n); } @@ -373,7 +512,19 @@ function toNaryString(num, n) { * ['/web/favicon.ico', '/web-scripts/dump', '/webalizer/logs'] => '/' */ function getCommonDirectoryPath(pathes) { - throw new Error('Not implemented'); + let answer = ''; + pathes = pathes.map(path => path.split('/')); + + while(pathes.length != 0) { + let tmp = pathes[0].shift(); + for (let i = 1; i < pathes.length; i++) { + if(pathes[i].shift() != tmp) { + return answer; + } + } + answer += tmp + '/'; + } + return answer; } @@ -396,7 +547,21 @@ function getCommonDirectoryPath(pathes) { * */ function getMatrixProduct(m1, m2) { - throw new Error('Not implemented'); + let n = m1.length, m = m2[0].length; + let answer = new Array(n); + for (let i=0; i < n; i++) + { + answer[i]=new Array(m); + } + for (let i = 0; i < m; i++) + for (let j = 0; j < n; j++) + answer[i][j]=0; + + for(let i = 0; i < n; i++) + for(let j = 0; j < m; j++) + for(let k = 0; k < m1[0].length; k++) + answer[i][j] += m1[i][k] * m2[k][j]; + return answer; } @@ -431,7 +596,27 @@ function getMatrixProduct(m1, m2) { * */ function evaluateTicTacToePosition(position) { - throw new Error('Not implemented'); + for (let i = 0; i < position.length; i++){ + if ((position[i][0] === position[i][1]) && (position[i][0] === position[i][2]) && (typeof position[i][0] != 'undefined')) + return position[i][0]; + } + let fl1 = true, fl2 = true; + for (let x = 1; x < position.length; x++){ + if (position[x][x] !== position[0][0]) + fl1 = false; + if (position[x][position.length - 1 - x] !== position[0][2]) + fl2 = false; + } + if (fl1 && typeof position[0][0] != undefined) + return position[0][0]; + if (fl2 && typeof position[0][2] != undefined) + return position[0][2]; + + for (let i = 0; i < position.length; i++) { + if ((position[0][i] === position[1][i]) && (position[0][i] === position[2][i]) && (typeof position[0][i] !== 'undefined')) + return position[0][i]; + } + return undefined; } diff --git a/task/07-yield-tasks.js b/task/07-yield-tasks.js index a2369790a..b707e10c3 100644 --- a/task/07-yield-tasks.js +++ b/task/07-yield-tasks.js @@ -5,7 +5,7 @@ * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/yield * - * * + * npm test ./test/07-yield-tests.js * ********************************************************************************************/ @@ -33,7 +33,19 @@ * */ function* get99BottlesOfBeer() { - throw new Error('Not implemented'); + let count = 99; + while (count >= 3) { + yield count + ' bottles of beer on the wall, ' + count + ' bottles of beer.'; + yield 'Take one down and pass it around, ' + --count + ' bottles of beer on the wall.'; + } + if (count = 2) { + yield count + ' bottles of beer on the wall, ' + count + ' bottles of beer.'; + yield 'Take one down and pass it around, ' + --count + ' bottle of beer on the wall.'; + } + yield '1 bottle of beer on the wall, 1 bottle of beer.'; + yield 'Take one down and pass it around, no more bottles of beer on the wall.'; + yield 'No more bottles of beer on the wall, no more bottles of beer.'; + yield 'Go to the store and buy some more, 99 bottles of beer on the wall.'; } @@ -47,7 +59,19 @@ function* get99BottlesOfBeer() { * */ function* getFibonacciSequence() { - throw new Error('Not implemented'); + yield 0; + yield 1; + + let last = 0; + let current = 1; + let new_val = 1; + + while (true){ + yield new_val; + last = current; + current = new_val; + new_val = last + current; + } } @@ -82,7 +106,14 @@ function* getFibonacciSequence() { * */ function* depthTraversalTree(root) { - throw new Error('Not implemented'); + let q1 = [root]; + while (q1.length) { + let node = q1.pop(); + yield node; + if (node.children) { + q1.push(...node.children.reverse()); + } + } } @@ -108,7 +139,15 @@ function* depthTraversalTree(root) { * */ function* breadthTraversalTree(root) { - throw new Error('Not implemented'); + let nodes = [root]; + for (let i = 0; i < nodes.length; i++) { + yield nodes[i]; + if ('children' in nodes[i]) { + for (let j = 0; j < nodes[i].children.length; j++) { + nodes.push(nodes[i].children[j]); + } + } + } } @@ -126,7 +165,25 @@ function* breadthTraversalTree(root) { * [ 1, 3, 5, ... ], [ -1 ] => [ -1, 1, 3, 5, ...] */ function* mergeSortedSequences(source1, source2) { - throw new Error('Not implemented'); + let src1 = source1(); + let src2 = source2(); + let i = src1.next().value; + let j = src2.next().value; + while (true) { + if ((i == undefined) && (j != undefined)) { + yield j; + j = src2.next().value; + } else if ((j == undefined) && (i != undefined)) { + yield i; + i = src1.next().value; + } else if ((i < j) && (i != undefined) && (j != undefined)) { + yield i; + i = src1.next().value; + } else if ((i >= j) && (i != undefined) && (j != undefined)) { + yield j; + j = src2.next().value; + } + } } diff --git a/task/08-objects-tasks.js b/task/08-objects-tasks.js index 610b1e7b2..0101777d1 100644 --- a/task/08-objects-tasks.js +++ b/task/08-objects-tasks.js @@ -5,7 +5,7 @@ * Plese read the following tutorial before implementing tasks: * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object * - * * + * npm test ./test/08-objects-tests.js * **************************************************************************************************/ @@ -23,7 +23,12 @@ * console.log(r.getArea()); // => 200 */ function Rectangle(width, height) { - throw new Error('Not implemented'); + this.width = width; + this.height = height; + + this.getArea = () => { + return this.width * this.height + } } @@ -38,7 +43,7 @@ function Rectangle(width, height) { * { width: 10, height : 20 } => '{"height":10,"width":20}' */ function getJSON(obj) { - throw new Error('Not implemented'); + return JSON.stringify(obj); } @@ -54,7 +59,13 @@ function getJSON(obj) { * */ function fromJSON(proto, json) { - throw new Error('Not implemented'); + let jsonObj = JSON.parse(json); + let obj = Object.create(proto); + for (let field in proto.prototype) + obj[field] = proto[field]; + for (let field in jsonObj) + obj[field] = jsonObj[field] + return Object.setPrototypeOf(jsonObj, proto); } @@ -105,35 +116,117 @@ function fromJSON(proto, json) { * * For more examples see unit tests. */ - +const CssSelector = (function () { + const extraPartsErrorMsg = 'Element, id and pseudo-element should not occur more then one time inside the selector'; + const invalidOrderErrorMsg = 'Selector parts should be arranged in the following order: element, id, class, attribute, pseudo-class, pseudo-element'; + const map = new WeakMap(); + + const State = Object.freeze({ + ELEMENT: 0, + ID: 1, + CLASS: 2, + ATTR: 3, + PSEUDO_CLASS: 4, + PSEUDO_ELEMENT: 5, + COMBINED_SELECTOR: 10 + }); + + function internal(ref) { + if (!map.get(ref)) { + map.set(ref, {}); + } + return map.get(ref); + } + + function addPart(scope, value, validState, nextState) { + const selector = internal(scope); + if (selector.alreadyCalled[validState]) { + throw new Error(extraPartsErrorMsg); + } + if (selector.currentState > validState) { + throw new Error(invalidOrderErrorMsg); + } + if (nextState) { + selector.alreadyCalled[validState] = true; + } + scope.selector += value; + selector.currentState = nextState || validState; + return scope; + } + + function CssSelector(selector, state) { + this.selector = selector || ''; + internal(this).currentState = state || State.ELEMENT; + internal(this).alreadyCalled = {}; + } + + CssSelector.prototype = { + + element: function (value) { + return addPart(this, value, State.ELEMENT, State.ID); + }, + + id: function (value) { + return addPart(this, `#${value}`, State.ID, State.CLASS); + }, + + class: function (value) { + return addPart(this, `.${value}`, State.CLASS); + }, + + attr: function (value) { + return addPart(this, `[${value}]`, State.ATTR); + }, + + pseudoClass: function (value) { + return addPart(this, `:${value}`, State.PSEUDO_CLASS); + }, + + pseudoElement: function (value) { + return addPart(this, `::${value}`, State.PSEUDO_ELEMENT, State.COMBINED_SELECTOR); + }, + + combine: function (second, combinator) { + const combinedSelector = `${this.selector} ${combinator} ${second.selector}`; + return new CssSelector(combinedSelector, State.COMBINED_SELECTOR); + }, + + stringify: function () { + return this.selector; + } + }; + + return CssSelector; + +}()); const cssSelectorBuilder = { - element: function(value) { - throw new Error('Not implemented'); + element: function (value) { + return new CssSelector().element(value); }, - id: function(value) { - throw new Error('Not implemented'); + id: function (value) { + return new CssSelector().id(value); }, - class: function(value) { - throw new Error('Not implemented'); + class: function (value) { + return new CssSelector().class(value); }, - attr: function(value) { - throw new Error('Not implemented'); + attr: function (value) { + return new CssSelector().attr(value); }, - pseudoClass: function(value) { - throw new Error('Not implemented'); + pseudoClass: function (value) { + return new CssSelector().pseudoClass(value); }, - pseudoElement: function(value) { - throw new Error('Not implemented'); + pseudoElement: function (value) { + return new CssSelector().pseudoElement(value); }, - combine: function(selector1, combinator, selector2) { - throw new Error('Not implemented'); + combine: function (selector1, combinator, selector2) { + return selector1.combine(selector2, combinator); }, }; diff --git a/task/09-functions-n-closures-tasks.js b/task/09-functions-n-closures-tasks.js index 6ba9dcedd..f232c7958 100644 --- a/task/09-functions-n-closures-tasks.js +++ b/task/09-functions-n-closures-tasks.js @@ -7,7 +7,7 @@ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments * * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures * - * * + * npm test ./test/09-functions-n-closures-tests.js * **********************************************************************************************/ @@ -26,7 +26,9 @@ * */ function getComposition(f,g) { - throw new Error('Not implemented'); + return function (x) { + return f(g(x)); + } } @@ -47,7 +49,9 @@ function getComposition(f,g) { * */ function getPowerFunction(exponent) { - throw new Error('Not implemented'); + return function (number) { + return Math.pow(number, exponent); + }; } @@ -65,7 +69,10 @@ function getPowerFunction(exponent) { * getPolynom() => null */ function getPolynom() { - throw new Error('Not implemented'); + let tmp = Array.from(arguments).reverse(); + return (x) => { + return tmp.reduce((prev, curr, index) => prev+curr*Math.pow(x,index),0); + }; } @@ -84,7 +91,10 @@ function getPolynom() { * memoizer() => the same random number (next run, returns the previous cached result) */ function memoize(func) { - throw new Error('Not implemented'); + let cashed = func(); + return function() { + return cashed + } } @@ -104,7 +114,16 @@ function memoize(func) { * retryer() => 2 */ function retry(func, attempts) { - throw new Error('Not implemented'); + return()=>{ + for (var i = 0; i < attempts;){ + try{ + return func(); + } catch(err){ + i += 1; + } + } + return i; + }; } @@ -132,7 +151,13 @@ function retry(func, attempts) { * */ function logger(func, logFunc) { - throw new Error('Not implemented'); + return function(...props) { + const str = `${func.name}(${JSON.stringify(Array.from(props)).slice(1, -1)}) `; + logFunc(str + 'starts'); + const result = func.apply(null, props); + logFunc(str + 'ends'); + return result; + }; } @@ -150,7 +175,10 @@ function logger(func, logFunc) { * partialUsingArguments(fn, 'a','b','c','d')() => 'abcd' */ function partialUsingArguments(fn) { - throw new Error('Not implemented'); + let arg = Array.from(arguments).slice(1); + return function () { + return fn.apply(null, arg.concat(Array.from(arguments))); + } } @@ -171,7 +199,12 @@ function partialUsingArguments(fn) { * getId10() => 11 */ function getIdGeneratorFunction(startFrom) { - throw new Error('Not implemented'); + let scope = startFrom; + return () => { + const toReturn = scope; + scope += 1; + return toReturn; + }; } diff --git a/task/10-katas-1-tasks.js b/task/10-katas-1-tasks.js index 5128b0695..59a679da2 100644 --- a/task/10-katas-1-tasks.js +++ b/task/10-katas-1-tasks.js @@ -4,7 +4,7 @@ * Returns the array of 32 compass points and heading. * See details here: * https://en.wikipedia.org/wiki/Points_of_the_compass#32_cardinal_points - * + * npm test ./test/10-katas-1-tests.js * @return {array} * * Example of return : @@ -17,8 +17,27 @@ * ] */ function createCompassPoints() { - throw new Error('Not implemented'); - var sides = ['N','E','S','W']; // use array of cardinal directions only! + let resArr = [], direction = "", degrees = 0; + var sides = ['N', 'E', 'S', 'W']; // use array of cardinal directions only! + for (let i = 0; i < sides.length; i++) { + let btwcardinal = (i == 0 || i == 2) ? (sides[i] + sides[i + 1]) + : (sides[i == 3 ? 0 : i + 1] + sides[i]); + for (let count = 0; count < 8; count++) { + switch (count) { + case 0: direction = sides[i]; break; + case 1: direction = sides[i] + 'b' + sides[i == 3 ? 0 : i + 1]; break; + case 2: direction = sides[i] + btwcardinal; break; + case 3: direction = btwcardinal + "b" + sides[i]; break; + case 4: direction = btwcardinal; break; + case 5: direction = btwcardinal + "b" + sides[i == 3 ? 0 : i + 1]; break; + case 6: direction = sides[i == 3 ? 0 : i + 1] + btwcardinal; break; + case 7: direction = sides[i == 3 ? 0 : i + 1] + "b" + sides[i]; break; + } + resArr.push({ abbreviation: direction, azimuth: degrees }); + degrees += 11.25; + } + } + return resArr; } @@ -56,7 +75,80 @@ function createCompassPoints() { * 'nothing to do' => 'nothing to do' */ function* expandBraces(str) { - throw new Error('Not implemented'); + const OPEN_BR = '{'; + const CLOSE_BR = '}'; + const SEPARATOR = ','; + + yield* parse(str); + + function parse(str) { + let items = ['']; + let pos = 0; + while (str[pos]) { + if (str[pos] !== OPEN_BR) { + items = combine(items, [readUntil([OPEN_BR])]); + } + else + { + pos += 1; + items = combine(items, parseExpr()); + } + } + return items; + + function parseExpr() { + let items = []; + let sepCount = 0; + while (str[pos] !== CLOSE_BR) + { + if (str[pos] === SEPARATOR) + { + pos += 1; + sepCount += 1; + } + else + { + items = items.concat(parseExprPart()); + } + } + if (items.length < sepCount + 1) items.push(''); + pos += 1; + return items; + } + + function parseExprPart() { + let items = ['']; + while (str[pos] !== SEPARATOR && str[pos] !== CLOSE_BR) + { + if (str[pos] !== OPEN_BR) + { + items = combine(items, [readUntil([SEPARATOR, OPEN_BR, CLOSE_BR])]); + } else + { + pos += 1; + items = combine(items, parseExpr()); + } + } + return items; + } + + function combine(leftItems, rightItems) { + const res = []; + for (let left of leftItems) + for (let right of rightItems) + res.push(left + right); + return res; + } + + function readUntil(chars) { + let res = ''; + while (str[pos] && chars.every(x => x !== str[pos])) { + res += str[pos]; + pos += 1; + } + return res; + } + } } @@ -88,7 +180,30 @@ function* expandBraces(str) { * */ function getZigZagMatrix(n) { - throw new Error('Not implemented'); + let mtx = []; + for (var i = 0; i < n; i++) + mtx[i] = []; + + var i=1, j=1; + for (var e = 0; e < n*n; e++) { + mtx[i-1][j-1] = e; + if ((i + j) % 2 == 0) { + if (j < n) + j++; + else + i += 2; + if (i > 1) + i--; + } else { + if (i < n) + i++; + else + j += 2; + if (j > 1) + j--; + } + } + return mtx; } @@ -113,7 +228,38 @@ function getZigZagMatrix(n) { * */ function canDominoesMakeRow(dominoes) { - throw new Error('Not implemented'); + let res = "" + dominoes.shift(); + let i = 0; + while (dominoes.length != 0) { + if (dominoes[i][0] == res[0]) { + res = dominoes[i].reverse() + res; + dominoes.splice(i, 1); + i = 0; + continue; + } + if (dominoes[i][1] == res[0]) { + res = dominoes[i] + res; + dominoes.splice(i, 1); + i = 0; + continue; + } + if (dominoes[i][0] == res[res.length - 1]) { + res = res + dominoes[i]; + dominoes.splice(i, 1); + i = 0; + continue; + } + if (dominoes[i][1] == res[res.length - 1]) { + res = res + dominoes[i].reverse(); + dominoes.splice(i, 1); + i = 0; + continue; + } + i++; + if (i == dominoes.length) + return false; + } + return true; } @@ -137,7 +283,20 @@ function canDominoesMakeRow(dominoes) { * [ 1, 2, 4, 5] => '1,2,4,5' */ function extractRanges(nums) { - throw new Error('Not implemented'); + let res = ""; + for (let j = 0; j < nums.length; j++) { + let i = 0; + if ((nums[j + 1] - nums[j] == 1) && (nums[j + 2] - nums[j] == 2)) { + while (nums[j + 1] - nums[j] == 1) { + i++; + j++; + } + res += `${nums[j - i]}-${nums[j]},`; + + } else + res += nums[j] + ","; + } + return res.slice(0, res.length - 1); } module.exports = { diff --git a/task/11-katas-2-tasks.js b/task/11-katas-2-tasks.js index 2a1a745cd..af3d4cbc2 100644 --- a/task/11-katas-2-tasks.js +++ b/task/11-katas-2-tasks.js @@ -1,6 +1,6 @@ 'use strict'; -/** +/** npm test ./test/11-katas-2-tests.js * Returns the bank account number parsed from specified string. * * You work for a bank, which has recently purchased an ingenious machine to assist in reading letters and faxes sent in by branch offices. @@ -34,7 +34,20 @@ * */ function parseBankAccount(bankAccount) { - throw new Error('Not implemented'); + const numbers = { + ' _ | ||_|': 0, + ' | |': 1, + ' _ _||_ ': 2, + ' _ _| _|': 3, + ' |_| |': 4, + ' _ |_ _|': 5, + ' _ |_ |_|': 6, + ' _ | |': 7, + ' _ |_||_|': 8, + ' _ |_| _|': 9 + }; + let res = bankAccount.split('\n').slice(0, 3).map(item => item.match(/.../g)); + return +res[0].map((item, index) => numbers[item + res[1][index] + res[2][index]]).join(""); } @@ -63,7 +76,20 @@ function parseBankAccount(bankAccount) { * 'characters.' */ function* wrapText(text, columns) { - throw new Error('Not implemented'); + if (text.length < columns){ + yield text; + return; + } + let num = 0; + let prevNum = 0; + let str = ""; + while ((num != -1) && (num <= columns)) { + prevNum = num; + num = text.indexOf(' ', num + 1); + } + str = text.slice(0, prevNum); + yield str; + yield* wrapText(text.slice(prevNum + 1), columns); } @@ -100,9 +126,111 @@ const PokerRank = { } function getPokerHandRank(hand) { - throw new Error('Not implemented'); + let rang = { + J: 11, + Q: 12, + K: 13, + A: 14 + } + let typeOfCard = { + '♥': 1, + '♦': 2, + '♠': 3, + '♣': 4 + } + let numberHand = hand.map((item, ind) => { + let _rang = item.slice(0, -1); + let _typeOfCard = item.slice(-1); + return rang[_rang] ? `${rang[_rang]}${typeOfCard[_typeOfCard]}` : `${_rang}${typeOfCard[_typeOfCard]}`; + }); + + switch (true) { + case (isSomeFlush(numberHand)): return isInOrderHand(numberHand) + ? PokerRank.StraightFlush : PokerRank.Flush; + case (isSomeOfKind(numberHand, 4)): return PokerRank.FourOfKind; + case (isFullHouseOrTwoPairs(numberHand, 3)): return PokerRank.FullHouse; + case (isInOrderHand(numberHand)): return PokerRank.Straight; + case (isSomeOfKind(numberHand, 3)): return PokerRank.ThreeOfKind; + case (isFullHouseOrTwoPairs(numberHand, 2)): return PokerRank.TwoPairs; + case (isSomeOfKind(numberHand, 2)): return PokerRank.OnePair; + default: return PokerRank.HighCard; + + } +} +function isSomeFlush(hand) { + let arr = hand.filter((item, i, arr) => { + return item.slice(-1) === arr[0].slice(-1); + }); + return arr.length == hand.length; } +function isInOrderHand(hand) { + let arr = hand.map((item, i) => +item.slice(0, -1)).sort((a, b) => a - b).filter((item, i, arr) => { + return arr[i + 1] ? (((arr[i + 1] == 14) && (arr[0] == 2)) + ? true : (arr[i + 1] - arr[i] == 1)) : ((arr[i] == 14) && (arr[0] == 2)) + ? true : (arr[i] - arr[i - 1] == 1); + }); + return arr.length == hand.length; +} +function isFullHouseOrTwoPairs(hand, kind) { + hand.sort(); + if (isSomeOfKind(hand, kind)) { + let arr = fixSizeOfArray(hand); + return isSomeOfKind(arr, 2); + } + return false; +} + +function fixSizeOfArray(hand) { + let arr = hand.map((item, i) => { + return item.slice(0, -1); + }); + let obj = {}; + for (let index = 0; index < arr.length; index++) { + obj[arr[index]] ? obj[arr[index]]++ : obj[arr[index]] = 1; + } + let max = 0; + let nameEl = ""; + for (let key in obj) { + if (obj[key] > max) { + max = obj[key]; + nameEl = key; + } + } + let newarr = hand.filter((item, i) => { + return nameEl != item.slice(0, -1); + }); + return newarr; +} + +function isSomeOfKind(hand, kind) { + let arr = hand.map((item, i) => { + return item.slice(0, -1); + }); + let obj = {}; + for (let index = 0; index < arr.length; index++) { + obj[arr[index]] ? obj[arr[index]]++ : obj[arr[index]] = 1; + } + let max = 0; + for (let key in obj) { + if (obj[key] > max) + max = obj[key]; + } + return max == kind; +} +function isTwoPairs(hand) { + hand.sort(); + if (isSomeOfKind(hand, 2)) { + let arr1 = hand.filter((item, i, arr) => { + return arr[i + 1] ? arr[i].slice(0, -1) === arr[i + 1].slice(0, -1) + : arr[i].slice(0, -1) === arr[i - 1].slice(0, -1); + }); + hand.splice(hand.indexOf(arr1[0]), 2); + return isSomeOfKind(hand, 2); + + } + return false; +} /** * Returns the rectangles sequence of specified figure. @@ -135,7 +263,43 @@ function getPokerHandRank(hand) { * '+-------------+\n' */ function* getFigureRectangles(figure) { - throw new Error('Not implemented'); + let a = figure.split('\n'); + let answer = []; + let check = function bar(n, m) { + let i; + let j; + for (i = m;; i++) { + if (a[n - 1][i] == undefined || a[n - 1][i] == ' ' || a[n] == undefined) return; + if (a[n][i] != ' ') break; + } + let w = i; + for (j = n;; j++) { + if (a[j] == undefined || a[j][w] == ' ') return; + if (a[j][w - 1] != ' ') break; + } + let h = j; + for (i = w - 1;; i--) { + if (a[h][i] == undefined || a[h][i] == ' ' || a[h - 1] == undefined) return; + if (a[h - 1][i] != ' ') break; + } + if (i + 1 != m) return; + for (j = h - 1;; j--) { + if (a[j] == undefined || a[j][m - 1] == ' ') return; + if (a[j][m] != ' ') break; + } + if (j + 1 != n) return; + n = h - n; + m = w - m; + answer.push('+' + '-'.repeat(m) + '+\n' + ('|' + ' '.repeat(m) + '|\n').repeat(n) + '+' + '-'.repeat(m) + '+\n'); + } + + a.pop(); + a.forEach((v, i) => v.split('').forEach((v, j) => { + if (v == '+') check(i + 1, j + 1); + })); + for (let index = 0; index < answer.length; index++) { + yield answer[index]; + } } diff --git a/task/12-katas-3-tasks.js b/task/12-katas-3-tasks.js index 5299be87d..a95216d7d 100644 --- a/task/12-katas-3-tasks.js +++ b/task/12-katas-3-tasks.js @@ -1,6 +1,6 @@ 'use strict'; -/** +/** npm test ./test/12-katas-3-tests.js * Returns true if word occurrs in the specified word snaking puzzle. * Each words can be constructed using "snake" path inside a grid with top, left, right and bottom directions. * Each char can be used only once ("snake" should not cross itself). @@ -28,7 +28,69 @@ * 'NULL' => false */ function findStringInSnakingPuzzle(puzzle, searchStr) { - throw new Error('Not implemented'); + class RouteMap { + constructor() { + this._route = {}; + this._width = puzzle[0].length; + this._height = puzzle.length; + } + + _key(x, y) { + return `${x},${y}`; + } + + markAvailable(x, y) { + this._route[this._key(x, y)] = false; + } + + markVisited(x, y) { + this._route[this._key(x, y)] = true; + } + + isAvailable(x, y) { + return x >= 0 + && x < this._width + && y >= 0 + && y < this._height + && !this._route[this._key(x, y)]; + } + } + + function* getSiblings(x, y) { + yield [x - 1, y]; + yield [x + 1, y]; + yield [x, y - 1]; + yield [x, y + 1]; + } + + function checkRoute(x, y, search, route) { + if (!route.isAvailable(x, y) || puzzle[y][x] !== search[0]) { + return false; + } + if (search.length === 1) { + return true; + } + route.markVisited(x, y); + const nextSearch = search.slice(1); + + for (let [sx, sy] of getSiblings(x, y)) { + if (checkRoute(sx, sy, nextSearch, route)) { + return true; + } + } + + route.markAvailable(x, y); + return false; + } + + for (let y = 0; y < puzzle.length; ++y) { + for (let x = 0; x < puzzle[0].length; ++x) { + if (checkRoute(x, y, searchStr, new RouteMap())) { + return true; + } + } + } + return false; } @@ -44,8 +106,29 @@ function findStringInSnakingPuzzle(puzzle, searchStr) { * 'ab' => 'ab','ba' * 'abc' => 'abc','acb','bac','bca','cab','cba' */ +function Perm(str) { + let ret = []; + + if (str.length == 1) return [str]; + if (str.length == 2) return str != str[1] + str[0] ? [str, str[1] + str[0]] : [str]; + + str.split('').forEach(function (chr, idx, arr) { + let sub = [...arr]; + sub.splice(idx, 1); + Perm(sub.join('')).forEach(function (perm) { + ret.push(chr + perm); + }); + }); + + return ret.filter((elem, pos, arr) => { + return arr.indexOf(elem) == pos; + }); +} function* getPermutations(chars) { - throw new Error('Not implemented'); + let ret = Perm(chars); + for (let i = 0; i < ret.length; i++) { + yield ret[i]; + } } @@ -65,7 +148,11 @@ function* getPermutations(chars) { * [ 1, 6, 5, 10, 8, 7 ] => 18 (buy at 1,6,5 and sell all at 10) */ function getMostProfitFromStockQuotes(quotes) { - throw new Error('Not implemented'); + if (!quotes.length) return 0; + let maxNum = Math.max.apply(null, quotes); + let indMax = quotes.lastIndexOf(maxNum); + return quotes.slice(0, indMax).reduce((prev, curr) => prev += maxNum - curr, 0) + + getMostProfitFromStockQuotes(quotes.slice(indMax + 1)); } @@ -91,13 +178,22 @@ function UrlShortener() { UrlShortener.prototype = { - encode: function(url) { - throw new Error('Not implemented'); + encode: function (url) { + var res = ''; + for (let i = 0; i * 2 < url.length; i++) { + res += String.fromCodePoint(url.codePointAt(2 * i) * 256 + (url.codePointAt(2 * i + 1) || 0)) + } + return res; }, - - decode: function(code) { - throw new Error('Not implemented'); - } + + decode: function (code) { + var res = ''; + for (let i = 0; i < code.length; i++) { + let c = code.codePointAt(i); + res += String.fromCodePoint(c / 256 | 0) + (c % 256 ? String.fromCodePoint(c % 256) : ''); + } + return res; + } }