makeevstranik/nodeHexlet
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Repository files navigation
solutions for tasks from hexlet nodejs developer course here explanation for each quizz and links to hexlet site 001-treeUnfolder.js return unfolded tree as string https://ru.hexlet.io/courses/js-trees/lessons/traversal/theory_unit /* *A / | \ B C D /| |\ E F G J В примере выбрана схема дерева на массивах. Каждый элемент дерева массив с 2 элементами Первый элемент массива это значение узла, второй (не обязателен)- дети. По пунктам: 1 извлекаем из дерева (или поддерева) значение и детей 2 Печатаем значение 3 Если нет детей выходим, если есть то для каждого вызываем рекурсивно функцию dfs. Все что будет дальше делаться по ходу курса, неизменно базируется на этом алгоритме. Попробуйте открыть редактор на своем компьютере и самостоятельно реализуйте эту функцию без подглядывания. Так вы убедитесь в том, что поняли происходящее.*/ #----------------------------------------------------------------------------------------- 002-treePrinter.js hexlet variant of 001 task. Just print tree. #------------------------------------------------------------------------------------------ 003-downcaseFileNames.js Реализуйте и экспортируйте функцию по умолчанию, которая принимает на вход директорию, приводит имена всех файлов в этой директории к нижнему регистру и возвращает ее наружу. --> Пример директории в константе treeToChec элемент дерева такой {children:[], meta:{}, name:'', type:''} *A(dir,/) | \ B(dir,etc) G(file,host) / \ C(dir,nginx) D(dir,consul) | E(file,config) особое внимание обратить на использование опреатора spread в решении (не мое с хекслета) #------------------------------------------------------------------------------------------ 004-treeMapper.js hexlet variant https://ru.hexlet.io/courses/js-trees/lessons/map/theory_unit Используем самописный map для отображения структуры. Функция, которая будет изменять элементы (но не структуру) передается, в виде functionForMap. Внимательно читать пояснения в коде. Интересное использование spread и деструктивного присваивания. #----------------------------------------------------------------------------------------- 005-treeMapper2.js Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход функцию-обработчик и дерево, а возвращает отображенное дерево. const actual = map(n => ({ ...n, name: n.name.toUpperCase() }), tree); Аналогично 004, но callback для самописного мап, возвращает обработынный узел целиком, а не только измененное поле. #--------------------------------------------------------------------------------------- 006-treeFilter.js hexlet variant https://ru.hexlet.io/courses/js-trees/lessons/filter/theory_unit a * /|\ B * C * d /| |\ e F G j Пример задачи: Отфильтровать только строчные листы дерева. Глядя на реализацию фильтра, видно что если нода не удовлетворяет предикату, то ее дети не рассматриваются вообще. В примере выше это нода B. Соответственно ее дети e и F даже не анализируются и отфильтровываются вместе с B. Интересно выглядит и вот эта запись children.map(c => filter(f, c)).filter(v => v). Дело в том что наш фильтр, не работает со списком, а работает с конкретным корневым узлом. Соответственно если мы обрабатываем детей, то в результате фильтрации количество детей не уменьшается. На их месте появляется null. Поэтому обход детей совершается используя map на массиве children с последующим filter. Тогда все null элементы отфильтруются. #----------------------------------------------------------------------------------- 007-treeFilter2.js ПРАКТИКА ЗАДАЧА - отфильтровать дерево по заданной функции (предикат) https://ru.hexlet.io/courses/js-trees/lessons/filter/exercise_unit filter.js Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход предикат и дерево, а возвращает отфильтрованное дерево по предикату. const actual = filter(n => n.type === 'directory', tree); #----------------------------------------------------------------------------------- 008-treeSample Образец дерева для дальнейшей обработки #------------------------------------------------------------------------------------ 009-treeReducer ЗАДАЧА- посчитать кол-во узлов дерева. Главная особенность reduce в наличии аккумулятора, который протаскивается сквозь все вызовы до самой глубины, а затем поднимается наверх и, в конце концов, возвращается наружу. Вызов reduce на каждом ребенке должен происходить с аккумулятором, протаскиваемым сквозь обработку каждого ребенка. Из-за этого получается, что снаружи есть reduce перебирающий children, в то время как каждый ребенок принимает на вход текущий acc внешнего reduce и запускает внутренний с этим аккумулятором. #------------------------------------------------------------------------------------ 010-treeReducer2 ПРАКТИКА https://ru.hexlet.io/courses/js-trees/lessons/reduce/exercise_unit ЗАДАЧА - посчитать кол-во узлов дерева, которое состоит из обьектов (нод), логика подсчета задается фунцией предикатом. treeReducer((acc, n) => acc + 1, tree, 0); // => 6 - простой пример treeReducer((acc, n) => (n.type === 'file' ? acc + 1 : acc), tree, 0); // считаем только файлы treeReducer((acc, n) => (n.type === 'directory' ? acc + 1 : acc), tree, 0); #----------------------------------------------------------------------------------- 011-findEmptyDirsDepth https://ru.hexlet.io/courses/js-trees/lessons/search/theory_unit ЗАДАЧА - найти в дереве пустые папки, поиск проводить только на заданную глубину. Так как наша реализация reduce не предоставляет информацию о том на какой глубине текущая нода, то можно выполнить обход вручную, передавая два аккумулятора, один с итоговым массивом, второй с уровнем вложенности. Несколько важных моментов: -Теперь нужно отслеживать текущую глубину, поэтому она передается в iter, с каждой глубиной увеличиваясь на единицу. -Если зашли глубже чем надо, то возвращаем результат. В остальном код такой же как и в обычном reduce. #--------------------------------------------------------------------------------------- 012-treeFactory ПРОБЛЕМА - в практике к уроку деревья, все деревья для тестов создаются с помощью скрытых функций mkdir, mkfile ЗАДАЧА - написать эти функции mkdir должна вернуть обьект c сигнатурой {children:[], meta:{}, name:'', type:'directory'} mkfile - {meta:{}, name:'', type:'file', size: {}} РЕШЕНИЕ - использовать классы, указанные функции просто вызывают конструкторы и возвращают готовые объекты. #--------------------------------------------------------------------------------------- 013-findFilesByName.js ПРАКТИКА https://ru.hexlet.io/courses/js-trees/lessons/search/exercise_unit ЗАДАЧА - Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход файловое дерево и подстроку, а возвращает список файлов, имена которых содержат эту подстроку. Обратите внимание на то что возвращается не просто имя файла, а полный путь до файла начиная от корня. Для построения путей, используйте функцию path.join. Файловое Дерево создается через вызов: const tree = mkdir('/', [ mkdir('etc', [ mkdir('apache'), mkdir('nginx', [ mkfile('nginx.conf', { size: 800 }), ]), mkdir('consul', [ mkfile('config.json', { size: 1200 }), mkfile('data', { size: 8200 }), mkfile('raft', { size: 80 }), ]), ]), mkfile('hosts', { size: 3500 }), mkfile('resolve', { size: 1000 }), ]); findFilesByName(tree, 'co'); // => ['/etc/nginx/nginx.conf', '/etc/consul/config.json'] #----------------------------------------------------------------------------- 013-h-findFilesByName.js Решение предыдущей задачи от хекслет. Более правильное и элегантное. Требует несложной дополнительной функции path. ВНИМАТЕЛЬНО ЧИТАЕМ ПОЯСНЕНИЯ К КОДУ, ЭТО ОЧЕНЬ ВАЖНАЯ ДЛЯ ПОНИМАНИЯ РАБОТЫ С ДЕРЕВЬЯМИ ЗАДАЧА! #--------------------------------------------------------------------------------- 014-flattenNestedList.js ПРАКТИКА ДЕРЕВЬЯ https://ru.hexlet.io/challenges/js_trees_flatten Реализуйте и экспортируйте по умолчанию функцию flatten, которая делает плоским вложенный массив. const list = [1, 2, [3, 5], [[4, 3], 2]]; // [1, 2, 3, 5, 4, 3, 2] #------------------------------------------------------------------------------- 015-convert.js ПРАКТИКА ДЕРЕВЬЯ https://ru.hexlet.io/challenges/js_trees_convertor Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход массив определенной структуры, и возвращающей объект полученный из этого массива. Массив устроен таким образом, что с помощью него можно представлять ассоциативные массивы. Каждое значение внутри него это массив из двух элементов, где первый элемент - ключ, а второй значение. В свою очередь если значение массив, то считается что это вложенное представление ассоциативного массива. Другими словами любой массив внутри исходного массива всегда рассматривается как данные, которые нужно конвертировать в объект. convert([]); // => {} convert([['key', 'value']]); // { key: 'value' } convert([['key', 'value'], ['key2', 'value2']]); // { key: 'value', key2: 'value2' } convert([ ['key', [['key2', 'anotherValue']]], ['key2', 'value2'] ]); // { key: { key2: 'anotherValue' }, key2: 'value2' } #---------------------------------------------------------------------------- 016-quickSort ПРАКТИКА // https://ru.hexlet.io/challenges/js_sequences_sort Реализуйте алгоритм быстрой сортировки. # -------------------------------------------------------------------------- 017-sortDeps.js ПРАКТИКА https://ru.hexlet.io/challenges/js_trees_dependencies Реализуйте и экспортируйте по умолчанию функцию sortDeps, которая принимает на вход список зависимостей и возвращает список (массив) отсортированных узлов. Пример: const deps1 = { mongo: [], tzinfo: ['thread_safe'], uglifier: ['execjs'], execjs: ['thread_safe', 'json'], redis: [], }; console.log(sortDeps(deps1)); // => ['mongo', 'thread_safe', 'tzinfo', 'json', 'execjs', 'uglifier', 'redis']; Независимые библиотеки и цепочки библиотек должны появляться в том порядке, в котором они встречались в исходной структуре. #--------------------------------------------------------------------------- 018-buildNode JS ПРОТОТИПЫ/ПОЛИМОРФИЗМ ПОДТИПОВ https://ru.hexlet.io/courses/js_prototypes/lessons/polymorphism/exercise_unit#theory buildNode.js Реализуйте и экспортируйте функцию по умолчанию, задача которой, создавать объект подходящего типа. Типы: SingleTag и PairedTag. Список имен тегов, которые относятся к SingleTag: hr, br, img. PairedTag.js Реализуйте тип PairedTag со следующим интерфейсом: Конструктор, который принимает на вход: name, attributes, body, children. Метод toString, который возвращает текстовое представление узла (html) на всю глубину. SingleTag.js Реализуйте тип SingleTag со следующим интерфейсом: Конструктор, который принимает на вход: name, attributes Метод toString, который возвращает текстовое представление узла (html) на всю глубину. Обратите внимание на то что у SingleTag нет body и children #-------------------------------------------------------------------------- 019-classNode JS НАСЛЕДОВАНИЕ https://ru.hexlet.io/courses/js_prototypes/lessons/inheritance/exercise_unit#theory Node.js Реализуйте базовый класс Node таким чтобы он содержал в себе общую логику PairedTag.js, SingleTag.js Реализуйте типы тегов как подтипы типа Node. [РЕАЛИЗУЕМ В ОТДЕЛЬНОМ ФАЙЛЕ, МЕНЯЕМ КЛАССЫ В 018] #------------------------------------------------------------------------- 020-magic JS ФУНКЦИИ КАК ОБЬЕКТЫ https://ru.hexlet.io/courses/js_prototypes/lessons/functions_as_objects/exercise_unit#theory Реализуйте функцию с бесконечным каррированием позволяющую делать слудующее const t = magic(1, 2)(3, 4, 5)(10, 10, 10)(1000, 1000); console.log('sum= ', t.sum, t == 5045); // true для представления функции в логическом операторе использовать встроенное свойство valueOf #------------------------------------------------------------------------ 021-classNodeImitation JS ПОЗДНЕЕ СВЯЗЫВАНИЕ В этом упражнении реализация наших типов (Node и ее подтипов) будет опираться на следующие свойства js: Функция это объект Позднее связывание Побочные эффекты (apply) Реализуйте базовый тип Node используя подход описанный в видео. PairedTag.js, SingleTag.js Реализуйте типы тегов как подтипы типа Node. Подсказки При определении функции внутри конструктора есть одна деталь. Функция создается каждый раз заново, а это ведет к двум проблемам: Лишний расход памяти. Ведь достаточно создать одну функцию и использовать ее повторно. Сравнение объектов даже в случае deepEqual будет давать false. Ведь функция это объект, а объекты друг другу не равны (даже если структура одинаковая), если это не один и тот же объект. А это сильно затрудняет проверки на равенство деревьев (или поддеревьев), а также делает крайне сложным тестирование. По этим причинам функцию нужно описывать вне конструктора (выше в файле), а внутри присваивать ее соответствующему свойству. #------------------------------------------------------------------------- 022-finalPrototypeClassNode JS ПРОТОТИПЫ, ЦЕПОЧКИ(ПСЕВДО-НАСЛЕДОВАНИЕ) https://ru.hexlet.io/courses/js_prototypes/lessons/prototype/theory_unit Node.js Реализуйте тип Node.js используя прототип. PairedTag.js, SingleTag.js Реализуйте прототипное наследование от типа Node. #--------------------------------------------------------------------------- 023-withoutTwoZeros ПРАКТИКА https://ru.hexlet.io/challenges/programming_basics_without_two_zeros/instance#community Реализуйте и экспортируйте по умолчанию функцию, которая принимает на вход два аргумента - количество нулей и количество единиц, и определяет сколько есть способов размещения этих нулей и единиц так, что бы не было двух нулей идущих подряд. Например, определим все способы размещения двух нулей и двух единиц. Существует шесть возможных способов размещения: 0011, 0101, 0110, 1001, 1010, 1100. В трех случаях содержится два нуля, идущих подряд: 0011, 1001 и 1100. Вычитаем их из общего числа и получаем три возможных способа: 0101, 0110 и 1010. Ответ - 3. Примеры использования: withoutTwoZeros(2, 2); // 3 withoutTwoZeros(1, 1); // 2 withoutTwoZeros(1, 3), // 4 withoutTwoZeros(2, 4); // 10 #--------------------------------------------------------------------------- 024-fileSystemSimulator hexlet-trees.js - имя файла в практическиом задании JS ОБРАБОТКА ОШИБОК ДЕРЕВЬЯ https://ru.hexlet.io/courses/js_errors/lessons/trees/theory_unit Tree.js Реализуйте недостающие части интерфейса типа Tree. hasChildren() hasChild(key) getParent() removeChild(key) getDeepChild(keys) getChildren() tree = new Tree('/'); tree.addChild('var') .addChild('lib') .addChild('run'); tree.addChild('etc'); tree.addChild('home'); // example: getDeepChild const subtree = tree.getDeepChild(['var', 'lib']); subtree.getKey(); // lib const parent = subtree.getParent(); parent.getKey(); // var tree.removeChild('home'); // true tree.removeChild('nonexistentNode'); // false Подсказки метод getChildren возвращает массив нод #------------------------------------------------------------------------ 025-fileSystemSimulator-FileLib hexletFS.js - имя файла в практическиом задании JS ОБРАБОТКА ОШИБОК ФАЙЛОВАЯ СИСТЕМА Файловая система должна корректно обрабатывать пустые пути, делая внутри нормализацию. То есть, если ей передать путь ///etc/config//my///, то он транслируется в /etc/config/my. HexletFs.js Реализуйте следующие части интерфейса типа HexletFs. isDirectory(path) isFile(path) mkdirSync(path) touchSync(path) - создает пустой файл. Пример: files.isDirectory('/etc'); // false files.mkdirSync('/etc'); files.isDirectory('/etc'); // true files.mkdirSync('/etc/nginx'); files.isDirectory('/etc/nginx'); // true files.isFile('/file.txt'); // false files.touchSync('/file.txt'); files.isFile('/file.txt'); // true Подсказки Реализуйте функцию getPathParts, которая разбивает путь на массив имен. Без этой функции не будет работать метод findNode, осуществляющий глубокий поиск файла (каталога) внутри текущего каталога. Для работы с путями используйте возможности встроенного в Node.js модуля Path. ДАННЫЙ ФАЙЛ БУДЕТ ИЗМЕНЕН В СЛЕДУЮЩЕМ ЗАДАНИИ ОРИГИНАЛ СМ. COMMIT 14.03.18 ДО 23.00 #-------------------------------------------------------------------------- 026-fileSystemSimulator-dirFileStatsNodeLib dir, file, node, stats, hexletFS.js - имя файла в практическиом задании JS ОБРАБОТКА ОШИБОК ИНФОРМАЦИЯ О ФАЙЛЕ Задание Задача состоит в том, чтобы реализовать тип Stats и его формирование посредством динамической диспетчеризации благодаря подтипам Node. Stats.js Реализуйте тип Stats со следующим интерфейсом: constructor isFile() isDirectory() Node.js Реализуйте надтип Node, интерфейсом которого являются функции: getStats() getName() Dir.js, File.js Реализуйте подтипы Dir и File (надтип Node). Варианты использования этих типов можно увидеть в файле HexletFs.js - ЗДЕСЬ ИЗМЕНЕННЫЙ ФАЙЛ fileSystemSimulator. ПРЯЧЕМ dir, file, node, stats В fileSystemSimulator-dirFileStatsNodeLib ОСНОВНОЙ ИНТЕРФЕЙС ПОКА ЧЕРЕЗ 025-fileSystemSimulator-FileLib #---------------------------------------------------------------- БЕЗ НОВОГО ФАЙЛА ИЗМЕНЯЕМ 026 JS ОБРАБОТКА ОШИБОК Задание HexletFs.js Реализуйте следующие возможности файловой системы HexletFs: mkdirpSync(path) Создает директории рекурсивно (в отличие от mkdir). Если в пути встречается файл, то возвращает false, т.к. нельзя создать директорию внутри файла. Если все отработало корректно, то возвращается true touchSync(path) Эта функция обновляет (в метаданных) время доступа к файлу и, как побочный эффект, создает файл, в случае его отсутствия. По этой причине команду touch часто используют как способ создать файл. В данном упражнении она делает только это. Если в пути встречается файл, то возвращает false, т.к. нельзя создать файл внутри файла Если все отработало корректно, то возвращается true readdirSync(path) Возвращает список файлов (и папок) указанной директории. Если директории не существует, то возвращает false Если передан файл, то возвращает false rmdirSync(path) Удаляет директорию. Если передан файл, то возвращает false и ничего не удаляет Если директории не существует, то возвращает false Если директория непустая, то возвращает false Если все отработало корректно, то возвращается true # ---------------------------------------------------------------- 027-diff.js JS: Асинхронное программирование Event Loop https://ru.hexlet.io/courses/js_async/lessons/event_loop/theory_unit Реализуйте и экспортируйте по умолчанию функцию, которая сравнивает два файла построчно. Сигнатура функции: (path1, path2, callback), где path1 и path2 — пути до первого и второго файла соответственно, а callback — это функция, которая будет вызвана после проведения сравнения. Сигнатура функции callback - (err, data). Результатом функции, который будет передан в коллбек, является массив, каждый элемент которого состоит из двух элементов. Первый — это строчка из первого файла, второй — это соответствующая строчка из второго. Если строки совпадают, то они не попадают в результат. Если в одном из файлов строка отсутствует, то в массиве подставляется null. Подробнее в примере: diff('fixtures/file4', 'fixtures/file5', (err, data) => { console.log(data); // [['text', 'ext'], ['', 'haha'], ['ehu', ''], ['', 'text'], ['aha', null]]; }); Содержимое файла file4 hello, world text ehu aha Содержимое файла file5 hello, world ext haha text Подсказки Данные, которые читаются из файла, преобразуются к строке используя метод toString. Альтернативный способ, это передача в readFile вместо двух, три аргумента. Подробнее можно посмотреть в документации. #-------------------------------------------------------------------------- 028-mapAsync JS: Асинхронное программирование Таймеры https://ru.hexlet.io/courses/js_async/lessons/timers/theory_unit Мои эксперементы с имитацией ф-ции map. Создан аналог хекслета но без рукурсии, на генераторе, работает несравнимо быстрее. Создан ассинхронный вариант на гернераторе без рекурсии. #-------------------------------------------------------------------------- 029-asyncFilter.js JS: Асинхронное программирование Таймеры https://ru.hexlet.io/courses/js_async/lessons/timers/theory_unit asyncFilter.js Реализуйте и экспортируйте по умолчанию функцию asyncFilter. const coll = [10, 53, true, false, '', NaN, 22]; asyncFilter(coll, v => typeof v === 'number', result => { console.log(result); // => [10, 53, NaN, 22] }); Так как фильтр асинхронный, то вызов предиката для каждой функции должен выполняться после setTimeout. Подсказки Проверка на соответствие внутри фильтра должна быть нестрогой как и в обычном фильтре: [10, 53, true, false, '', NaN, 22].filter(v => v); // => [ 10, 53, true, 22 ] #-------------------------------------------------------------------------- 030-asyncFilter2.js JS: Асинхронное программирование Работа с ошибкми https://ru.hexlet.io/courses/js_async/lessons/errors/theory_unit Реализуйте и экспортируйте по умолчанию функцию filter. Отфильтрованная коллекция должна сохранять порядок элементов. filter(['file1', 'file2', 'file3'], (filePath, callback) => { fs.access(filePath, err => { callback(null, !err) }); }, (err, results) => { // results now equals an array of the existing files });