Skip to content

Latest commit

 

History

History
 
 

3.2-array-proto-hocs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

Домашнее задание к занятию 3.2 «Прототип массива, функции высшего порядка»

Задача №1. Ускорение долгих вычислений

Паша — разработчик из компании “Тындекс” встретился с такой проблемой: иногда функция может считать результат очень долго, даже когда ей передавались одинаковые параметры, ведь она каждый раз пересчитывает результат.

Создайте функцию, которая сможет “запоминать” результаты другой функции, которую ей передают в качестве аргумента.

Для того, чтобы запомненные результаты не занимали всю память, сделайте массив запомненных результатов ограниченным: когда элементов становится больше 10, то самый старый результат удаляется, а новый -- добавляется.

Процесс реализации

1. sleep

Реализуйте функцию, эмулирующую продолжительную работу. Так как в JavaScript отсутствует стандартный механизм приостановки выполнения кода на определённый промежуток времени, а с асинхронным кодом вы ещё не знакомы, то реализуйте искуственное замедление любого кода:

function sleep(milliseconds) 
{
  let e = new Date().getTime() + milliseconds;
  while (new Date().getTime() <= e) {}
}

2. sum

Реализуйте функцию, которая сможет работать с произвольным количеством аргументов. Например, это может быть суммирование всех переданных чисел. Так же для эмуляции длительного выполнения функции добавьте вызов реализованного замедления:

function sum(...args) {
  // Замедление на половину секунды.
  sleep(500); // Можно использовать другое значение замедления.
  return args.reduce((sum, arg) => {
    return sum += +arg;
  }, 0);
}

3. compareArrays

Создайте вспомогательную функцию compareArrays( arr1, arr2 ), которая с помощью функции высшего порядка будет сравнивать значения двух массивов. Если массивы имеют одинаковые значения на одинаковых индексах, compareArrays должна выдавать true (иначе false). Используйте метод every для сравнения элементов одного массива с соответствующими элементами другого массива.

Пример вызова

compareArrays([8, 9], [6]); // false, разные значения
compareArrays([8, 9, 5, 4], [8, 9, 5, 4, 8, 3, 5]); // false, разные значения
compareArrays([9, 2, 4, 8, 2], [9, 2, 4]); // false, разные значения
compareArrays([1, 2, 3], [2, 3, 1]); // false, разные индексы, хотя и одинаковые значения
compareArrays([8, 1, 2], [8, 1, 2]); // true

4. memorize

Создайте функцию memorize(fn, limit), у которой fn - функция, которая производит вычисления, limit - ограничение по количеству результатов.

1. Вызов результата

Функция memorize должна возвращать функцию. В полученную функцию мы будем передавать аргументы так, как могли бы делать это с fn:

const mSum = memorize(sum, 5); // 5 результатов может хранится в памяти

// Вызов этих функций даёт один и тот же результат
sum(3, 4); // 7
/* 
  разница только в том, что mSum запоминает результат (7)
  и повторно не делает вычисления
 */
mSum(3, 4); // 7

Предусмотрите возможность передачи произвольного количества аргументов!

2. Внутренняя память

Объявите внутри memorize массив memory, который будет хранить историю вызовов возвращаемой memorize функции (в примере выше это mSum). Каждый элемент массива memory - объект с двумя свойствами:

{
  args, // массив аргументов, с которыми была вызвана функция
  result // результат работы
}

Для примера, mSum(3, 4) поместит в memory такой объект:

{
  args: [3, 4],
  result: 7 // сумма 3 и 4
}

3. Работа возвращаемой функции

Функция, которую возвращает memorize в качестве результата работы, выполняет следующую последовательность действий:

1. Поиск

С помощью функции find найдите в массиве memory, объект, у которого в свойстве args находится такой же массив, как и массив аргументов с которыми была вызвана возвращаемая memorize функция.

Например, для вызова mSum таким образом:

const mSum = memorize(sum, 2);
mSum(3, 4); // 7
mSum(1, 3); // 4

memory будет выглядеть так:

[
    {
        args: [3, 4],
        result: 7
    },
    {
        args: [1, 3],
        result: 4
    }
]

После повторного вызова mSum(3, 4) необходимо найти запись, которая «помнит» о том, что ранее был вызов с этими аргументами, то есть вот эту:

{
    args: [3, 4],
    result: 7
}

Для сравнения массивов используйте функцию compareArrays, написанную вами ранее.

2. Вычисление

  1. Если история о вызове функции fn найдена, то функция должна вернуть свойство result найденного объекта.
  2. В ином случае, необходимо:
    1. Вычислить результат fn с переданными аргументами.
    2. Добавить запись о вызове fn в memory.
    3. При количестве элементов memory более limit удалить лишнее.
    4. Вернуть результат fn с переданными аргументами.

5. testCase

Реализуйте функцию, которая сможет тестировать скорость работы функции sum и её оптимизированную версию (результат функции memorize). Ваша функция testCase должна принимать функцию testFunction, и название таймера процессорного времени.

  1. Создайте массив, содержащий массивы аргументов, например [ [1,2,3], [1,2], [1,2,3], [1,2], [9,5,2,4] ]. Обязательно добавьте повторяющиеся и не повторяющиеся массивы чисел (которые будут аргументами).
  2. С помощью метода console.time запустите счётчик процессорного времени (метод принимает строку, по которой будет идентифицировать счётчик). Название счетчика принимайте аргументом функции.
  3. Создайте цикл, который выполняйте много раз (например 100). С помощью метода forEach вызывайте вашу тестируемую функцию с перебираемыми аргументами. Используйте spread - оператор для разделения массива аргументов на аргументы (либо используйте метод apply). Таким образом вызывайте вашу функцию количество_элементов_массива_аргументов * количество_итераций_цикла раз.
  4. В конце цикла остановите счётчик процессорного времени с помощью console.timeEnd (передав ту же строку, что и при запуске).
  5. Запустите функцию testCase для измерения времени выполнения функции sum и её оптимизированной версии (результата функции memorize).
  6. Сделайте выводы об оптимизации вычислений.
  7. Уберите из функции sum задержку. Снова запустите функции-тесты и сделайте выводы о работе вашего кода.
  8. Результаты вызовов напишите комментариями в коде или сообщением в личном кабинете.

Критерии выполнения

  1. Добавьте внутрь передаваемой функции fn вывод в консоль системной информации о том, что функция вызвана не из памяти.
  2. Добавьте внутрь memorize вывод в консоль о том, что результат берётся из памяти.
  3. Убедитесь на основе вывода в консоль, что параметр limit работает корректно.
  4. Критерии 1-3 используйте для удобства понимания того, как ведёт себя код. При реализации п.п.5 (измерения времени работы функций) вывод на консоль желательно убрать, так как при множественном запуске вашего кода консоль засорится.
  5. Используйте циклы только в запуске измерительных тестов. В остальных случаях используйте функции высшего порядка.

Требования для выполнения домашней работы

Решение задач

  1. Перейти в папку задания, например, для первого задания cd ./3.2-array-proto-hocs.
  2. Открыть файл task.js в вашем редакторе кода и выполнить задание.
  3. Открыть файл index.html в вашем браузере и с помощью консоли DevTools убедиться в правильности выводимых результатов.
  4. Добавить файл task.js в индекс git с помощью команды git add %file-path%, где %file-path% - путь до целевого файла, например, для первого задания git add array-proto-hocs/task.js.
  5. Сделать коммит используя команду git commit -m '%comment%', где %comment% - это произвольный комментарий к вашему коммиту, например, для первого задания 'first commit array-proto-hocs'.
  6. Опубликовать код в репозиторий homeworks с помощью команды git push -u origin master.
  7. Прислать ссылку на репозиторий через личный кабинет на сайте Нетологии.

Никаких файлов прикреплять не нужно.

Любые вопросы по решению задач задавайте в Slack-канале.