Некоторые логические задачи на JS
Реализация аналога Math.pow
Нужна функция, принимающая число и степень (в виде целого числа, например 3 или -2), выдающая значение этого числа в указанной степени.
Особенность: должен осуществляться рекурсивный вызов, без циклов и глобальных переменных.
Решение:
var pow = function(a,n,start,isMinus){
if (!start) var start = a;
if (n == 0 && isMinus) return start/a;
else if (n == 0) return 1;
else if (n == 1) return a;
else if (n > 1) {
return pow(a*start, n-1, start)
}
else if (n < 0) {
return pow(a*start, n+1, start, true)
}
}
Или вариант без лишних параметров, но с замыканием:
var pow = function(a,n){
var start = a;
var f = function(a,n,isMinus){
if (n == 0 && isMinus) return start/a;
else if (n == 0) return 1;
else if (n == 1) return a;
else if (n > 1) {
return f(a*start, n-1)
}
else if (n < 0) {
return f(a*start, n+1, true)
}
}
return f(a,n);
}
Реализовать экземпляр класса А, в котором к одному из родительских методов добавить свой функционал
function A() {
A.do = function(){
console.log("A")
}
}
var B = new A;
B.do = function(){
B.constructor.do()
console.log("B")
}
B.do();
Стоить обратить внимание, как задаётся метод класса А: this будет ссылаться на глобальный объект.
Задача про мост и 4 человека
Итак, есть 4 человека, 1 фонарь и 1 мост.
1-й проходит мост за 1 мин, 2-й за 2, третий за 5 мин, 4-й за 10.
Нужно перевести всех на другую сторону моста. Одновременно на мосту могут находиться не более 2 чел. Без фонаря на мосту находиться невозможно. Люди могут ходить как туда, так и обратно, но только с одним единственным фонарём.
Задача: как сделать так, чтобы перевести всех за максимально короткое время?
Правильный ответ: 17 мин.
Решение очевидно алгоритмически, но неочевидно житейски. Нужно скомпоновать две самые затратные операции. Схема такая:
1) 1+2 => 2 мин
2) обратно идёт 2-й => 2 мин
3) 5+10 => 10 мин
4) обратно идёт 1-й => 1 мин
5) 1+2 => 2 мин
Итого 2+2+10+1+2 = 17 мин.
Объединение массивов в проверкой на уникальность
Задача.
Дано: два массива разной длины. Требуется их объединить, выкинув неуникальные значения.
Решение 1
a и b - исходные массивы
function(a,b){
var res = [];
a = a.concat(b);
a = a.sort(numbers);
function numbers(a,b) {
if (a > b) return 1;
if (a < b) return -1;
}
res.push(a[0]);
for (var i=0; i < a.length; i++) {
if (i > 0) {
if (a[i] == a[i-1]) continue
else res.push(a[i])
}
}
return res
}
Тут время выполнения будет стремиться к log(n) + время на sort()
Решение 2
function(a,b){
var res = [];
for (var i=0; i < a.length; i++) {
res[a[i]] = a[i];
}
for (var j=0; j < b.length; j++) {
res[b[j]] = b[j];
}
return Object.keys(res)
}
Тут время выполнения будет стремиться к log(n) + время работы Object.keys(). Решение основано на том, что свойство объекта просто перезатирается новым значением, если используется одно и то же свойство, дублирования свойств не будет.