freeCodeCamp/curriculum/challenges/ukrainian/10-coding-interview-prep/rosetta-code/factors-of-a-mersenne-numbe...

5.8 KiB
Raw Blame History

id title challengeType forumTopicId dashedName
598eea87e5cf4b116c3ff81a Фактори числа Мерсенна 5 302264 factors-of-a-mersenne-number

--description--

Число Мерсенна - це число у вигляді 2P-1.

Якщо P є простим, то число Мерсенна може бути простим числом Мерсенна. (Якщо P не є простим, число Мерсенна також не є простим.)

У пошуку простих чисел Мерсенна вигідно усунути експоненти, знайшовши невеликий фактор перед початком, потенційно довжину, [тест Лукас-Лемер](https://rosettacode.org/wiki/Lucas-Lehmer test "Lucas-Lehmer test").

Існують дуже ефективні алгоритми визначення, чи число ділиться на 2P-1 (або відповідно, якщо 2P мод (число) = 1).

Деякі мови вже мають вбудовані реалізації цієї операції експонента і моду (так званої modPow або подібні).

Нижче зрозуміло, як реалізувати цей modPow самостійно:

Наприклад, обчислимо 223 мод 47.

Перетворимо експонент 23 у двійковий, ви отримаєте 10111. Починаючи з квадрат = 1, повторно піднести до квадрату.

Видаліть верхній біт степеня, і якщо його 1 помножити на square на основу піднесення до степеня (2), потім обчислити квадрат модуль 47.

Використовуйте результат модуля від останнього кроку як початкове значення square в наступному кроці:

Видалити необов'язковий
квадрат, помножений на 2 мод 47
------------ ------- ---
1*1 = 1 0111 1*2 = 2
2*2 = 4 0 111 без 4
4*4 16 = 1 11 16*2 = 32
32*32 4*32 1024 1 1024*2 = 2048
27*2 = 7291 *2 = 1458 1*2 = 1458

Починаючи з 2 мод 47 = 1, 47 є фактором 2P-1.

(Щоб побачити це, відніміть 1 від обох сторін: 223-1 = 0 мод 47)

Оскільки ми показали, що 47 це фактор, 223-1 не є простим.

Подальші властивості Мерсенного числа дозволяють нам ще більше вдосконалити процес.

Будь-який фактор, q з 2P-1 повинен бути у вигляді 2kP+1, k це додатне ціле число або нуль. Крім того, q має бути 1 або 7 mod 8.

Нарешті будь-який потенційний множник q має бути [prime](https://rosettacode.org/wiki/Primality by Trial Division "Primality by Trial Division").

Як і в інших алгоритмах пробного ділення, алгоритм припиняється, коли 2kP+1 > sqrt(N). Ці в першу чергу тести працюють лише з цифрами Мерсенна, де P - це просте число. Наприклад, M4=15 не дає ніяких чинників, використовуючи ці технології, але фактори в 3 та 5, жоден з яких не відповідає 2kP+1.

--instructions--

Використовуючи вказаний метод, знайти коефіцієнт 2р-1.

--hints--

check_mersenne має бути функцією.

assert(typeof check_mersenne === 'function');

check_mersenne(3) має повернути рядок.

assert(typeof check_mersenne(3) == 'string');

check_mersenne(3)повинен повертатися рядок M3 = 2^3-1 is prime.

assert.equal(check_mersenne(3), 'M3 = 2^3-1 is prime');

check_mersenne(23) повинен повертатися як рядок M23 = 2^23-1 is composite with factor 47.

assert.equal(check_mersenne(23), 'M23 = 2^23-1 is composite with factor 47');

check_mersenne(929) повинен повертати рядок M929 = 2^929-1 is composite with factor 13007.

assert.equal(
  check_mersenne(929),
  'M929 = 2^929-1 is composite with factor 13007'
);

--seed--

--seed-contents--

function check_mersenne(p) {

}

--solutions--

function check_mersenne(p){
    function isPrime(value){
      for (let i=2; i < value; i++){
        if (value % i == 0){
          return false;
        }
        if (value % i != 0){
          return true;
         }
      }
    }

    function trial_factor(base, exp, mod){
      let square, bits;
      square = 1;
      bits = exp.toString(2).split('');
      for (let i=0,ln=bits.length; i<ln; i++){
        square = Math.pow(square, 2) * (bits[i] == 1 ? base : 1) % mod;
      }
      return (square == 1);
    }

    function mersenne_factor(p){
      let limit, k, q;
      limit = Math.sqrt(Math.pow(2,p) - 1);
      k = 1;
      while ((2*k*p - 1) < limit){
        q = 2*k*p + 1;
        if (isPrime(q) && (q % 8 == 1 || q % 8 == 7) && trial_factor(2,p,q)){
          return q; // q is a factor of 2**p-1
        }
        k++;
      }
      return null;
    }
  let f, result;
  result="M"+p+" = 2^"+p+"-1 is ";
  f = mersenne_factor(p);
  result+=f == null ? "prime" : "composite with factor "+f;
  return result;
}