Некоторые логические задачи на 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(). Решение основано на том, что свойство объекта просто перезатирается новым значением, если используется одно и то же свойство, дублирования свойств не будет.