Имам нужда от помощ за оптимизиране на функция

По принцип искам да генерирам ъгъл (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

Въз основа на предишен мой въпрос: Разбъркване на Fischer Yates в скрипт за кафе

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