diff --git a/Hex.js b/Hex.js new file mode 100644 index 000000000..1d9c912a1 --- /dev/null +++ b/Hex.js @@ -0,0 +1,29 @@ +'use strict'; + +const HEX_SYMBOLS = + ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; +const HEX_BASE = 16; + +/** + * Определяет является ли символ шеснадцатиричным + * @param {String} symbol Шестнадцатиричный символ, в виде строки длины 1 + * @returns {Boolean} Когда символ шестнадцатиричный, то true, а иначе false + */ +function isHexadimal(symbol) { + return HEX_SYMBOLS.includes(symbol); +} + +/** + * Переводит Шестнадцатиричный символ в десятичное число + * @param {String} symbol Шестнадцатиричный символ, в виде строки длины 1 + * @returns {Number} Десятичнеое число, переведённое из шестнадчатиричного символа + */ +function getNumber(symbol) { + return HEX_SYMBOLS.indexOf(symbol); +} + +module.exports = { + HEX_BASE, + isHexadimal, + getNumber +}; diff --git a/warmup.js b/warmup.js index eefda9891..33a16ce38 100644 --- a/warmup.js +++ b/warmup.js @@ -1,5 +1,14 @@ 'use strict'; +/** + * Проверяет является ли аргумент числом + * @param {Number} something Нет требований к аргументу + * @returns {Boolean} Если является числом, то true, а иначе false + */ +function isNumber(something) { + return typeof something === 'number'; +} + /** * Складывает два целых числа * @param {Number} a Первое целое @@ -8,7 +17,14 @@ * @returns {Number} Сумма аргументов */ function abProblem(a, b) { - // Ваше решение + if (!isNumber(a)) { + throw new TypeError('First argument is not a number'); + } + if (!isNumber(b)) { + throw new TypeError('Second argument is not a number'); + } + + return a + b; } /** @@ -19,7 +35,26 @@ function abProblem(a, b) { * @returns {Number} Век, полученный из года */ function centuryByYearProblem(year) { - // Ваше решение + if (!isNumber(year)) { + throw new TypeError('Argument is not a number'); + } + if (year < 0) { + throw new RangeError('Argument is negative'); + } + const YEARS_IN_CENTURY = 100; + + return Math + .floor(year / YEARS_IN_CENTURY) + // получили индекс года + 1; // получили номер года +} + +/** + * определяет является ли аргумент строкой + * @param {String} something Нет требований к аргументу + * @returns {Boolean} Если является строкой, то true, а иначе false + */ +function isString(something) { + return typeof something === 'string'; } /** @@ -30,7 +65,30 @@ function centuryByYearProblem(year) { * @returns {String} Цвет в формате RGB, например, '(255, 255, 255)' */ function colorsProblem(hexColor) { - // Ваше решение + const lowerHexColor = hexColor.toLocaleLowerCase(); + if (!isString(lowerHexColor)) { + throw new TypeError('Color in Format HEX don\'t gives as a string'); + } + const COLOR_RANGE_ERROR = new RangeError('Value of color is incorrect'); + if (lowerHexColor.length !== 7 || lowerHexColor[0] !== '#') { + throw COLOR_RANGE_ERROR; + } + const { + BASE_HEX, + isHexadimal, + getNumber + } = require('./Hex'); + for (let i = 1; i < lowerHexColor.length; i++) { + if (!isHexadimal(lowerHexColor[i])) { + throw COLOR_RANGE_ERROR; + } + } + lowerHexColor = lowerHexColor.split('#').shift(); + const number1 = getNumber(lowerHexColor[0]) * BASE_HEX + getNumber(lowerHexColor[1]); + const number2 = getNumber(lowerHexColor[2]) * BASE_HEX + getNumber(lowerHexColor[3]); + const number3 = getNumber(lowerHexColor[4]) * BASE_HEX + getNumber(lowerHexColor[5]); + + return '(' + number1 + ',' + number2 + ',' + number3 + ')'; } /** @@ -41,7 +99,26 @@ function colorsProblem(hexColor) { * @returns {Number} Число Фибоначчи, находящееся на n-ой позиции */ function fibonacciProblem(n) { - // Ваше решение + if (!isNumber(n) !== 'number') { + throw new TypeError('Position in row give\'s not as a number'); + } + if (n < 0) { + throw new RangeError('Position in row not positve integer'); + } + if (n === 0 || n === 1) { + return n; + } + let q = 0; + let qPlus1 = 1; + let i = 2; + while (i < n) { + const next = q + qPlus1; + q = qPlus1; + qPlus1 = next; + i++; + } + + return q + qPlus1; } /** @@ -51,7 +128,25 @@ function fibonacciProblem(n) { * @returns {(Any[])[]} Транспонированная матрица размера NxM */ function matrixProblem(matrix) { - // Ваше решение + const ARRAY_2D_RANGE_ERROR = new TypeError('transfered not an 2D array'); + if (!Array.isArray(matrix)) { + throw ARRAY_2D_RANGE_ERROR; + } + for (let i = 0; i < matrix.length; i++) { + if (!Array.isArray(matrix[i])) { + throw ARRAY_2D_RANGE_ERROR; + } + } + const newMatrix = []; + const m = matrix[0].length; + const n = matrix.length; + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + newMatrix[i][j] = matrix[j][i]; + } + } + + return newMatrix; } /** @@ -63,7 +158,19 @@ function matrixProblem(matrix) { * @returns {String} Число n в системе счисления targetNs */ function numberSystemProblem(n, targetNs) { - // Ваше решение + if (!isNumber(n)) { + throw new TypeError('Transfered not a decimal number'); + } + if (!isNumber(targetNs)) { + throw new TypeError('Base of number system isn\'t a number'); + } + const maxNumberSystem = 36; + const minNumberSystem = 2; + if ((targetNs - minNumberSystem) * (maxNumberSystem - targetNs) < 0) { + throw new RangeError('Base of number system not belong [2, 36]'); + } + + return n.toString(targetNs); } /** @@ -72,7 +179,11 @@ function numberSystemProblem(n, targetNs) { * @returns {Boolean} Если соответствует формату, то true, а иначе false */ function phoneProblem(phoneNumber) { - // Ваше решение + if (phoneNumber.length !== 15) { + return false; + } + + return /8-800-\d{3}-\d{2}-\d{2}/.test(phoneNumber); } /** @@ -82,7 +193,16 @@ function phoneProblem(phoneNumber) { * @returns {Number} Количество улыбающихся смайликов в строке */ function smilesProblem(text) { - // Ваше решение + if (!isString(text)) { + throw new TypeError('Text didn\'t transfer like a string'); + } + const smilesArray = [':-)', '(-:']; + let amount = 0; + smilesArray.forEach(function (smile) { + amount += text.split(smile).length - 1; + }); + + return amount; } /** @@ -92,7 +212,34 @@ function smilesProblem(text) { * @returns {'x' | 'o' | 'draw'} Результат игры */ function ticTacToeProblem(field) { - // Ваше решение + let x0 = 1; + let y0 = 1; + let delta = Math.PI / 4; + const iterationQuantity = Math.round(2 * Math.PI / delta); + for (let i = 0; i < iterationQuantity; i++) { + const dX = Math.round(Math.cos(i * delta)); + const dY = Math.round(Math.sin(i * delta)); + if (field[x0][y0] === field[x0 + dX][y0 + dY] && + field[x0][y0] === field[x0 - dX][x0 - dY]) { + return field[x0][y0]; + } + } + x0 = 0; + y0 = 0; + delta = Math.PI / 2; + iterationQuantity = Math.round(2 * Math.PI / delta); + for (let i = 0; i < iterationQuantity; i++) { + const dX = Math.round(Math.cos(-i * delta)); + const dY = Math.round(Math.sin(-i * delta)); + if (field[x0][y0] === field[x0 + dX][y0 + dY] && + field[x0][y0] === field[x0 + 2 * dX][y0 + 2 * dY]) { + return field[x0][y0]; + } + x0 += 2 * dX; + y0 += 2 * dY; + } + + return 'draw'; } module.exports = {