From b7b7dbb6ec7bf609132ece889b24979fa3352193 Mon Sep 17 00:00:00 2001 From: sarthakgupta1907-cell Date: Mon, 2 Nov 2026 14:38:27 +0530 Subject: [PATCH] feat: add Euler totient function algorithm --- Maths/EulerTotient.js | 29 ++++++++++++++++++++++++ Maths/test/EulerTotient.test.js | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 Maths/EulerTotient.js create mode 100644 Maths/test/EulerTotient.test.js diff --git a/Maths/EulerTotient.js b/Maths/EulerTotient.js new file mode 100644 index 0000000000..af79f8cdfa --- /dev/null +++ b/Maths/EulerTotient.js @@ -0,0 +1,29 @@ +/** + * @function eulerTotient + * @description Euler's totient function counts the positive integers up to n + * that are relatively prime to n (i.e., gcd(k, n) = 1). + * @param {number} n - A positive integer greater than 0 + * @returns {number} - Count of integers from 1 to n coprime to n + * @see https://en.wikipedia.org/wiki/Euler%27s_totient_function + * @example eulerTotient(9) => 6 + * @example eulerTotient(1) => 1 + */ +const eulerTotient = (n) => { + if (!Number.isInteger(n) || n < 1) { + throw new TypeError('Input must be a positive integer') + } + let result = n + let p = 2 + let temp = n + while (p * p <= temp) { + if (temp % p === 0) { + while (temp % p === 0) temp = Math.floor(temp / p) + result -= Math.floor(result / p) + } + p++ + } + if (temp > 1) result -= Math.floor(result / temp) + return result +} + +export { eulerTotient } diff --git a/Maths/test/EulerTotient.test.js b/Maths/test/EulerTotient.test.js new file mode 100644 index 0000000000..f6527cbe17 --- /dev/null +++ b/Maths/test/EulerTotient.test.js @@ -0,0 +1,40 @@ +import { eulerTotient } from '../EulerTotient.js' + +describe('eulerTotient', () => { + test('eulerTotient(1) returns 1', () => { + expect(eulerTotient(1)).toBe(1) + }) + + test('eulerTotient(2) returns 1', () => { + expect(eulerTotient(2)).toBe(1) + }) + + test('eulerTotient(9) returns 6', () => { + expect(eulerTotient(9)).toBe(6) + }) + + test('eulerTotient(10) returns 4', () => { + expect(eulerTotient(10)).toBe(4) + }) + + test('eulerTotient(36) returns 12', () => { + expect(eulerTotient(36)).toBe(12) + }) + + test('eulerTotient of a prime returns prime minus 1', () => { + expect(eulerTotient(7)).toBe(6) + expect(eulerTotient(13)).toBe(12) + }) + + test('throws TypeError for zero', () => { + expect(() => eulerTotient(0)).toThrow(TypeError) + }) + + test('throws TypeError for negative input', () => { + expect(() => eulerTotient(-5)).toThrow(TypeError) + }) + + test('throws TypeError for float', () => { + expect(() => eulerTotient(1.5)).toThrow(TypeError) + }) +})