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>' => '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<n/2+1; i++){
+        if(n%i==0){
+            return false;
+        }
+    }
+    return true;
 }
 
 /**
@@ -221,7 +241,12 @@ function isPrime(n) {
  *   toNumber(new Number(42), 0) => 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;
+    }
 }