Мне нужна помощь в оптимизации функции

В основном я хочу создать угол (0-360 градусов), который не находится в указанном диапазоне ряда других углов. Я уже сделал эту функцию для проверки двух углов:

function check(angle1, angle2, range) {
    var diff = angle1 - angle2;

    if(Math.abs(diff % 360) <= range || (360-Math.abs(diff % 360)) <= range) {
        return true;
    } else {
        return false;
    }
}

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

Я думаю, это сработает:

var others = [array of objects];

...

for(var i = 0; i < 360; i++) {
    var pass = true;
    for(var n = 0; n < others.length; n++) {
        if(check(i, others[n].angle, 5)) {
            pass = false;
            break;
        }
    }
    if(pass) return i;
}

return false;

Однако это много циклов, и я бы предпочел случайный угол, а не увеличение. Есть ли более быстрый и лучший способ сделать это? Спасибо.

Изменить: решил сделать что-то подобное, идея пришла из ответа @TheBronx.

var angles = [];

var range = 5;

function alterAngle(a, n) {
  var angle = a + n;
  if(angle < 0) angle = 360 + angle;
  if(angle > 360) angle = angle - 360;
  return angle;
}



// in the function

var angle = Math.floor(Math.random() * 360);

if(angles.indexOf(angle) == -1) {
  for(var i = -range; i <= range; i++)
    angles.push(alterAngle(angle, i));
}

person Suffick    schedule 21.02.2013    source источник
comment
Возможно, Code Review может быть более подходящим сайтом для этого вопроса?   -  person Shawn Chin    schedule 21.02.2013
comment
Просто любопытно, диапазон это маленькое значение? как 5º? Сколько углов может быть в худшем случае?   -  person Salvatorelab    schedule 21.02.2013
comment
Являются ли ваши углы целыми числами?   -  person Billy Moon    schedule 21.02.2013
comment
Вероятно, максимум около 30 углов, и да, углы — это целые числа.   -  person Suffick    schedule 21.02.2013
comment
Ответьте, пожалуйста, на вопрос @TheBronx о радиусе действия.   -  person Likurg    schedule 21.02.2013


Ответы (3)


Идея. Представьте, что ваши углы — это карты в колоде. Как только вы сгенерируете случайный угол, вы удалите этот угол из колоды, а также углы в пределах вашего диапазона. Когда вам нужно сгенерировать новый угол, вместо генерации случайного числа от 0 до 360 вам просто нужно «выбрать карту». Это всегда будет работать, если у вас нет дополнительных «карт».

Проблема в том, что у вас много карт? Хватит ли у вас времени инициализировать "карточки" при старте?

Просто идея... Не знаю, хорошая она или нет, но выглядит многообещающе.

person Salvatorelab    schedule 21.02.2013
comment
Это блестящая идея! Я просто проверю это, я опубликую это, если это работает. Спасибо. - person Suffick; 21.02.2013
comment
Управлять диапазонами оказывается довольно сложно. Я думал, что смогу просто соединить кусок массива, но тогда вы в конечном итоге соедините переходы там, где вы ранее соединили. Это может работать до сих пор, если я выясню это. - person Suffick; 21.02.2013
comment
да, удалить проблема. Как только вы выберете угол, вы должны проверить и удалить до range*2 углов. Но проверка не занимает много времени, и вы можете удалить все углы сразу (когда вы знаете, где начинать и заканчивать стык)... это может сработать. - person Salvatorelab; 21.02.2013
comment
В итоге я сделал противоположное тому, что вы сказали, добавив весь диапазон в массив и проверив, находится ли сгенерированный угол в этом массиве. Вы подали мне идею, спасибо большое. - person Suffick; 21.02.2013

Вот этот

if(Math.abs(diff % 360) <= range || (360-Math.abs(diff % 360)) <= range) {
    return true;
  } else {
    return false;
}

вы могли бы сделать таким образом, это сократит операции

return Math.abs(diff % 360) <= range || (360-Math.abs(diff % 360)) <= range;
person Likurg    schedule 21.02.2013
comment
и если вы сохраните Math.abs(diff % 360) в переменной, вам не нужно вычислять ее дважды. Вероятно, это не то решение, которое ему нужно, но поскольку он использует function check много раз, оптимизация имеет смысл. - person Salvatorelab; 21.02.2013

Основываясь на моем предыдущем вопросе: Фишер Йейтс перемешивает кофейный скрипт

var counter, i, permutations, shuffle, x, _i;

// Fischer Yates shuffle algorithm
shuffle = function(arr, required) {
  var i, index, randInt, _i, _ref, _ref1, _ref2;
  if (required == null) {
    required = arr.length;
  }
  randInt = function(n) {
    return Math.floor(n * Math.random());
  };
  if (required > arr.length) {
    required = arr.length;
  }
  if (required <= 1) {
    return arr[randInt(arr.length)];
  }
  for (i = _i = _ref = arr.length - 1, _ref1 = arr.length - required; _ref <= _ref1 ? _i <= _ref1 : _i >= _ref1; i = _ref <= _ref1 ? ++_i : --_i) {
    index = randInt(i + 1);
    _ref2 = [arr[i], arr[index]], arr[index] = _ref2[0], arr[i] = _ref2[1];
  }
  return arr.slice(arr.length - required);
};


// generate array of all possible angles
var angles = []
for(i=0;i<360;i++){ angles.push(i) }

// shuffle as many as you need (20 in this example)
var shuffled = shuffle(angles,20)

// check the result
console.log(shuffled)

// simply deal off values from this shuffled array as needed
person Billy Moon    schedule 21.02.2013