Реализация китайской теоремы об остатках в JavaScript

#javascript #typescript #algorithm #crt

#javascript #typescript #алгоритм #crt

Вопрос:

Я пытался решить задачу Advent of Code 2020, день 13, часть 2. Я нашел много подсказок, говорящих о чем-то, называемом китайской теоремой об остатках. Я пробовал некоторые реализации, следующие за nodejs-chinesse-remainders от npm, но эта реализация кажется довольно старой (2014), а также требует дополнительных библиотек для больших случаев Int.

Как я мог бы реализовать модульную мультипликативную обратную? Как я мог бы реорганизовать алгоритм CRT, определенный в модуле npm, для которого я предоставил ссылку?

Ответ №1:

В качестве самостоятельного ответа и с целью создания вики, чтобы найти это решение для тех, кому в будущем понадобится реализация CRT на javascript / typescript:

Сначала подумайте о том, чтобы реализовать модульную мультипликативную обратную, для этой задачи мы пытаемся найти x такое, что: a*x % modulus = 1

 const modularMultiplicativeInverse = (a: bigint, modulus: bigint) => {
  // Calculate current value of a mod modulus
  const b = BigInt(a % modulus);
    
    // We brute force the search for the smaller hipothesis, as we know that the number must exist between the current given modulus and 1
    for (let hipothesis = 1n; hipothesis <= modulus; hipothesis  ) {
        if ((b * hipothesis) % modulus == 1n) return hipothesis;
    }
      // If we do not find it, we return 1
    return 1n;
}
 

Затем, следуя статье и приведенному вами образцу кода:

 const solveCRT = (remainders: bigint[], modules: bigint[]) => {
    // Multiply all the modulus
    const prod : bigint = modules.reduce((acc: bigint, val) => acc * val, 1n);
    
    return modules.reduce((sum, mod, index) => {
        // Find the modular multiplicative inverse and calculate the sum
    // SUM( remainder * productOfAllModulus/modulus * MMI ) (mod productOfAllModulus) 
        const p = prod / mod;
        return sum   (remainders[index] * modularMultiplicativeInverse(p, mod) * p);
    }, 0n) % prod;
}
 

Таким образом, вы используете функции ES6, такие как reduce

Чтобы это работало с bigints, массив остатков и модулей должен соответствовать BigInt в ES2020

Например:

   x mod 5 = 1
  x mod 59 = 13
  x mod 24 = 7
 
 // Declare the problem and execute function
// You can not parse them to BigInt here, but TypeScript will complain of operations between int and bigint
const remainders : bigint[] = [1, 13, 7].map(BigInt)
const modules: bigint[] = [5, 59, 24].map(BigInt)

solveCRT(remainders, modules) // 6031