2017-01-25 2 views
3

Я пытаюсь выполнить скрипт функции, которая принимает два числа и возвращает наименьший общий кратный, который также делится на все числа между этими числами, то, что у меня есть, работает только от 1,1 до 1,12, но почему-то перестает работать на 1,13. Другой набор, подобный 12,14, но я не могу понять, почему и что такое шаблон.Javascript наименее распространенный множественный алгоритм

function smallestCommons(arr) { 
    arr.sort(function(a, b) { 
     return a-b; 
    }); 
    var arr1 = []; 
    var arr2 = []; 
    for (var k = arr[0]; k<=arr[1]; k++) { 
     arr1.push(k); 
    } 
    function remainder(val1, val2) { 
     return val1%val2; 
    } 
    var b = arr1.reduce(function(a, b) { 
     return a*b; 
    }); 
    var i = arr1[arr1.length-1]*arr1[arr1.length-2]; 
    while (i<=b) { 
     for (var m = 0; m<arr1.length; m++) { 
      var a = remainder(i, arr1[m]); 
      arr2.push(a); 
     } 
     var answer = arr2.reduce(function(c, d) { 
      return c+d; 
     }); 
     if (answer === 0) { 
      return i; 
     } else { 
      arr2 = []; 
      i++; 
     } 
    } 
} 
+0

Я получаю сообщение об ошибке, что есть потенциал бесконечного цикла с переменной я, когда я [1,13], но не с [1,12], я не знаю, почему ? – Keli

ответ

0

Это правда! Результат [1, 13] равен 360360. После этого мы имеем [1, 14].

14 = 2 * 7 и теперь мы 360360 делимы на 2 и 7, поэтому ответ 360360 снова.

[1, 15]: 15 = 3 * 5, и результат такой же.

[1, 16]: результат 720720.

[1, 17]: результат: 12252240

[1, 18]: 18 = 2 * 9 и результат 12252240 же, как 17

[1, 19]: для моего компьютера этот процесс настолько тяжелый и не может этого сделать. Но в сильной машине это сработает. Обещаю. Но ваш код не очень хорош в производительности.

+0

Я не думаю, что LCM для '[1,2,3 .., 16]' - 360360 с 360360/16 = 22522.5. Это 720720, а '[1,2, ..., 17]' равно 12252240. – Redu

+0

Да, я забыл, что 8 делимо на 2, а для числа, которое должно быть делимым до 16, недостаточно разделить на 8 и 2 . Но результат тот же. Ваш код верен, но с очень низкой производительностью. –

+0

ОК, но как мой код очень низкий в производительности ..? Он решает LCM для '[1,2,3, ..., 215,216]' всего лишь 0,25 мс. Этого недостаточно ...? – Redu

0

Насколько я могу судить, ваш алгоритм дает вам правильный ответ.

Я далек от того, чтобы быть профессиональным программистом, так что любой, кто хочет, пожалуйста, дайте варианты, чтобы улучшить мой код или его стиль :)

Если вы хотите, чтобы иметь возможность проверить ответ самостоятельно вы можете проверить эту скрипку: https://jsfiddle.net/cowCrazy/Ld8khrx7/

function multiplyDict(arr) { 
    arr.sort(function (a, b) { 
    return a - b; 
    }); 

    if (arr[0] === 1) { 
    arr[0] = 2; 
    } 
    var currentArr = []; 

    for (var i = arr[0]; i <= arr[1]; i++) { 
    currentArr.push(i); 
    } 
    var primeDivs = allPrimes(arr[1]); 
    var divsDict = {}; 

    for (var j = currentArr[0]; j <= currentArr[currentArr.length -1]; j++){ 
    divsDict[j] = []; 
    if (primeDivs.indexOf(j) > -1) { 
     divsDict[j].push(j); 
    } else { 
     var x = j; 
     for (var n = 2; n <= Math.floor(j/2); n++) { 
     if (x % n === 0) { 
      divsDict[j].push(n); 
      x = x/n; 
      n--; 
      continue; 
     } 
     } 
    } 
    } 
    return divsDict; 
} 

function allPrimes(num) { 
    var primeArr = []; 

    var smallestDiv = 2; 

    loopi: 
    for (var i = 2; i <= num; i++) { 
    loopj: 
    for (var j = smallestDiv; j <= largestDiv(i); j++) { 
     if (i % j === 0) { 
     continue loopi; 
     } 
    } 
    primeArr.push(i); 
    } 
    return primeArr; 
} 

function largestDiv (a) { 
    return Math.floor(Math.sqrt(a)); 
} 

multiplyDict([1,13]); 

это дает словарь запрашиваемого массива и делители каждого элемента. оттуда вы можете пойти самостоятельно, чтобы убедиться, что ваш алгоритм делает правильную работу или вы можете проверить его здесь: https://jsfiddle.net/cowCrazy/kr04mas7/

Я надеюсь, что это помогает

1

Я думаю, вы можете сделать следующее в JavaScript; Он может вычислять общий LCM до массива элементов 216, например [1,2,3,...,216] менее чем за 0,25 мс.

function gcd(a,b){ 
 
    var t = 0; 
 
    a < b && (t = b, b = a, a = t); // swap them if a < b 
 
    t = a%b; 
 
    return t ? gcd(b,t) : b; 
 
} 
 

 
function lcm(a,b){ 
 
    return a/gcd(a,b)*b; 
 
} 
 

 
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13], 
 
    brr = Array(216).fill().map((_,i) => i+1), // limit before Infinity 
 
result = arr.reduce(lcm); 
 
console.log(result); 
 
console.time("limit"); 
 
result = brr.reduce(lcm); 
 
console.timeEnd("limit"); 
 
console.log(result);

Смежные вопросы