В качестве практики вам необходимо реализовать несколько функций. Весь код по этому заданию пишите в файле functions.js
.
- Вспомните задание с отладкой. Оружия из того задания вам пригодятся для практики изученных функций.
- Так как в файл подключается RPG-игра, в которой присутствует много вывода, то для удобства следует убрать весь вывод игры. Используйте
console.clear();
для очистки консоли - Создайте начальный массив оружий (используйте этот набор оружий в данном порядке):
const weapons = [new Knife(), new Staff(), new Axe(), new StormStaff(), new LongBow(), new Bow()];
- Все последующие функции следует реализовывать без использования циклов
- Напишите функцию
getNames
, которая будет возвращать имена всех оружий. - Напишите функцию
getCountReliableWeapons
, которая принимает значение прочности и возвращает количество оружий больше принимаемой прочности - Напишите функцию
hasReliableWeapons
, которая принимает значение прочности и возвращает вердикт: есть ли оружия прочней принимаемой прочности? - Напишите функцию
getReliableWeaponsNames
, которая принимает значение прочности и возвращает имена оружий, которые прочней полученного значения. - Напишите функцию
getTotalDamage
, которая вернёт общую сумму урона всех оружий. - Необязательно. Напишите функцию, которая принимает массив чисел и значение суммы, а возвращает значение количества чисел, которое необходимо суммировать до получения переданной суммы. Если набранной суммы не хватает, то возвращает общее количество элементов.
//возвращает 4, т.к. 1+2+3=6 (3 числа), а 1+2+3+5=11 (4 числа)
getValuestCountToSumValues([1,2,3,5,2,7,3,5,2], 10);
//возвращает 6, т.к. 1+2+3+5+2=13 (5 чисел), а 1+2+3+5+2+7=20 (6 чисел)
getValuestCountToSumValues([1,2,3,5,2,7,3,5,2], 20);
Внимание Запуск тестов может зависать из-за неоптимальности RPG-игры. Проблема решается закрытием вкладки с тестами и повторным открытием.
Паша — разработчик из компании “Тындекс” встретился с такой проблемой: иногда функция может считать результат очень долго, даже когда ей передавались одинаковые параметры, ведь она каждый раз пересчитывает результат.
Создайте функцию, которая сможет “запоминать” результаты другой функции, которую ей передают в качестве аргумента.
Для того, чтобы запомненные результаты не занимали всю память, сделайте массив запомненных результатов ограниченным: когда элементов становится больше 10, то самый старый результат удаляется, а новый -- добавляется.
Реализуйте функцию, эмулирующую продолжительную работу. Так как в JavaScript отсутствует стандартный механизм приостановки выполнения кода на определённый промежуток времени, а с асинхронным кодом вы ещё не знакомы, то реализуйте искуственное замедление любого кода:
function sleep(milliseconds)
{
let e = new Date().getTime() + milliseconds;
while (new Date().getTime() <= e) {}
}
Реализуйте функцию, которая сможет работать с произвольным количеством аргументов. Например, это может быть суммирование всех переданных чисел (вы можете использовать любую функцию). Так же для эмуляции длительного выполнения функции добавьте вызов реализованного замедления:
function sum(...args) {
// Замедление на половину секунды.
sleep(100); // Можно использовать другое значение замедления.
return args.reduce((sum, arg) => {
return sum += +arg;
}, 0);
}
Создайте вспомогательную функцию 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
- Создайте функцию
memorize(fn, limit)
, у которой fn - функция, которая производит вычисления, limit - ограничение по количеству результатов.
Функция memorize должна возвращать функцию. В полученную функцию мы будем передавать аргументы так, как могли бы делать это с fn:
const mSum = memorize(sum, 5); // 5 результатов может хранится в памяти
// Вызов этих функций даёт один и тот же результат
sum(3, 4); // 7
/*
разница только в том, что mSum запоминает результат (7)
и повторно не делает вычисления
*/
mSum(3, 4); // 7
Предусмотрите возможность передачи произвольного количества аргументов!
Объявите внутри memorize массив memory, который будет хранить историю вызовов возвращаемой memorize функции (в примере выше это mSum). Каждый элемент массива memory - объект с двумя свойствами (массивом аргументов и результатом функции):
{ args, result }
Для примера, mSum(3, 4) поместит в memory такой объект:
{ args: [3, 4], result: 7 }
Функция, которую возвращает memorize в качестве результата работы, выполняет следующую последовательность действий:
С помощью функции 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, написанную вами ранее.
- Если история о вызове функции fn найдена, то функция должна вернуть свойство result найденного объекта.
- В ином случае, необходимо:
- Вычислить результат fn с переданными аргументами.
- Добавить запись о вызове fn в memory.
- При количестве элементов memory более limit удалить лишнее.
- Вернуть результат fn с переданными аргументами.
- Переданная функция fn не должна вызываться более одного раза. Иначе вместо оптимизации вычисления только увеличатся.
Реализуйте функцию, которая сможет тестировать скорость работы функции sum
и её оптимизированную версию (результат функции memorize
). Ваша функция testCase
должна принимать функцию testFunction
, и название таймера процессорного времени.
- Создайте массив, содержащий массивы аргументов, например
[ [1,2,3], [1,2], [1,2,3], [1,2], [9,5,2,4] ]
. Обязательно добавьте повторяющиеся и не повторяющиеся массивы чисел (которые будут аргументами). - С помощью метода
console.time
запустите счётчик процессорного времени (метод принимает строку, по которой будет идентифицировать счётчик). Название счетчика принимайте аргументом функции. - Создайте цикл, который выполняйте много раз (например 100). С помощью метода
forEach
вызывайте вашу тестируемую функцию с перебираемыми аргументами. Используйтеspread
- оператор для разделения массива аргументов на аргументы (либо используйте метод apply). Таким образом вызывайте вашу функцию количество_элементов_массива_аргументов * количество_итераций_цикла раз. - В конце цикла остановите счётчик процессорного времени с помощью
console.timeEnd
(передав ту же строку, что и при запуске). - Запустите функцию
testCase
для измерения времени выполнения функцииsum
и её оптимизированной версии (результата функцииmemorize
). - Сделайте выводы об оптимизации вычислений.
- Уберите из функции
sum
задержку. Снова запустите функции-тесты и сделайте выводы о работе вашего кода. - Результаты вызовов напишите комментариями в коде или сообщением в личном кабинете.
Напишите функцию memorize, которая должна возвращать другую функцию. Сначала пустую функицю. Это важный момент, так как если это у вас не получается, значит вы не усвоили материал занятия функций высшего порядка.
const resultFunction = memorize();
resultFunction(); // <= должно вызываться без ошибок
Переделайте возвращаемую функцию, чтобы она принимала набор аргументов и выводила их на консоль. Тоесть выполнение должно быть примерно такое:
const resultFunction = memorize();
resultFunction(1,2,3,4); // <= должно вывести: 1,2,3,4
Переделайте memorize
, чтобы она принимала функцию, а возвращала функцию, которая будет выполнять эту полученную функцию
const resultFunction = memorize(a => a ** 2);
resultFunction(2); // <= должно вывести: 4
resultFunction(5); // <= должно вывести: 25
Важно! Вы не должны возвращать полученную функцию, вы должны вернуть другую функцию, которая будет выполнять эти вычисления.
В memorize
сделайте массив с некоторыми значениями объектов. Например возьмите тот же пример из задания:
[
{
args: [3, 4],
result: 7
},
{
args: [1, 3],
result: 4
}
]
Из аргументов возвращаемой функции с помощью find находите объект в памяти. Тоесть вы создали этот массив и дальше выполнение должно быть примерно таким:
const resultFunction = memorize((a,b) => a+b);
resultFunction(3,4); // <= должно вывести: 7
resultFunction(5,6); // <= ничего не найдёт в памяти.
Необходимо в памяти найти такой объект у которого в свойстве args
будет такое же значение, как и массив полученных аргументов. Для сравления массивов используйте compareArrays
.
Если получится сделать прошлый пункт, то половина дела сделано, останется только доделать пункт 2.3.1. Вычисление и очистить массив памяти (что бы он изначально был пустой). И так же добавить возможность добавления предела количества сохраняемых объектов в памяти.
- Добавьте внутрь передаваемой функции fn вывод в консоль системной информации о том, что функция вызвана не из памяти.
- Добавьте внутрь memorize вывод в консоль о том, что результат берётся из памяти.
- Убедитесь на основе вывода в консоль, что параметр limit работает корректно.
- Критерии 1-3 используйте для удобства понимания того, как ведёт себя код. При реализации п.п.5 (измерения времени работы функций) вывод на консоль желательно убрать, так как при множественном запуске вашего кода консоль засорится.
- Используйте циклы только в запуске измерительных тестов. В остальных случаях используйте функции высшего порядка.
- браузер;
- редактор кода, например Sublime или Visual Studio Code;
- аккаунт на GitHub (инструкция по регистрации на GitHub);
- система контроля версий Git, установленная локально (инструкция по установке Git).
- запуск всех тестов должен успешно выполнять все тесты:
- Перейти в папку задания, например, для первого задания
cd ./3.2-array-proto-hocs
. - Открыть файл
task.js
в вашем редакторе кода и выполнить задание. - Открыть файл
index.html
в вашем браузере и с помощью консоли DevTools убедиться в правильности выводимых результатов. - Добавить файл
task.js
в индекс git с помощью командыgit add %file-path%
, где %file-path% - путь до целевого файла, например, для первого заданияgit add array-proto-hocs/task.js
. - Сделать коммит используя команду
git commit -m '%comment%'
, где %comment% - это произвольный комментарий к вашему коммиту, например, для первого задания 'first commit array-proto-hocs'. - Опубликовать код в репозиторий homeworks с помощью команды
git push -u origin master
. - Прислать ссылку на репозиторий через личный кабинет на сайте Нетологии.
Никаких файлов прикреплять не нужно.
Любые вопросы по решению задач задавайте в Slack-канале.