diff --git a/Project-Euler/Problem026.js b/Project-Euler/Problem026.js new file mode 100644 index 0000000000..edee6f2299 --- /dev/null +++ b/Project-Euler/Problem026.js @@ -0,0 +1,71 @@ +/** + * Problem - Longest Recurring Cycle + * + * @see {@link https://projecteuler.net/problem=26} + * + * Find the value of denominator < 1000 for which 1/denominator contains the longest recurring cycle in its decimal fraction part. + * + * A unit fraction (1/denominator) either terminates or repeats. We need to determine the length of the repeating sequence (cycle) + * for each fraction where the denominator is between 2 and 999, and find the denominator that produces the longest cycle. + */ + +/** + * Main function to find the denominator < limit with the longest recurring cycle in 1/denominator. + * + * @param {number} limit - The upper limit for the denominator (exclusive). + * @returns {number} The denominator that has the longest recurring cycle in its decimal fraction part. + */ +function findLongestRecurringCycle(limit) { + /** + * Calculates the length of the recurring cycle for 1 divided by a given denominator. + * + * @param {number} denominator - The denominator of the unit fraction (1/denominator). + * @returns {number} The length of the recurring cycle in the decimal part of 1/denominator. + */ + function getRecurringCycleLength(denominator) { + // A map to store the position of each remainder encountered during division + const remainderPositions = new Map() + let numerator = 1 // We start with 1 as the numerator (as we're computing 1/denominator) + let position = 0 // This tracks the position of each digit in the decimal sequence + + // Continue until the remainder becomes 0 (terminating decimal) or a cycle is found + while (numerator !== 0) { + // If the remainder has been seen before, we've found the start of the cycle + if (remainderPositions.has(numerator)) { + // The length of the cycle is the current position minus the position when the remainder first appeared + return position - remainderPositions.get(numerator) + } + + // Record the position of this remainder + remainderPositions.set(numerator, position) + + // Multiply numerator by 10 to simulate long division and get the next digit + numerator = (numerator * 10) % denominator + position++ // Move to the next digit position + } + + // If numerator becomes 0, it means the decimal terminates (no cycle) + return 0 + } + + let maxCycleLength = 0 // Store the maximum cycle length found + let denominatorWithMaxCycle = 0 // Store the denominator corresponding to the longest cycle + + // Iterate through each possible denominator from 2 up to (limit - 1) + for (let denominator = 2; denominator < limit; denominator++) { + // Calculate the cycle length for the current denominator + const cycleLength = getRecurringCycleLength(denominator) + + // Update the maximum length and the corresponding denominator if a longer cycle is found + if (cycleLength > maxCycleLength) { + maxCycleLength = cycleLength + denominatorWithMaxCycle = denominator + } + } + + // Return the denominator that has the longest recurring cycle + return denominatorWithMaxCycle +} + +// Exporting the main function for use in other modules +export { findLongestRecurringCycle } diff --git a/Project-Euler/Problem027.js b/Project-Euler/Problem027.js new file mode 100644 index 0000000000..dac47a4552 --- /dev/null +++ b/Project-Euler/Problem027.js @@ -0,0 +1,61 @@ +/** + * Problem - Quadratic Primes + * + * @see {@link https://projecteuler.net/problem=27} + * + * The quadratic expression n^2 + an + b, where |a| < 1000 and |b| ≤ 1000, + * produces a positive prime for consecutive values of n, starting with n = 0. + * Find the product of the coefficients, a and b, for the quadratic expression that + * produces the maximum number of primes for consecutive values of n. + */ + +/** + * Main function to find the coefficients a and b that produce the maximum number + * of consecutive primes for the quadratic expression n^2 + an + b. + * + * @returns {{maxPrimes: number, product: number}} An object containing the maximum number of primes + * and the product of coefficients a and b. + */ +function findMaxConsecutivePrimes() { + /** + * Checks if a number is prime. + * + * @param {number} n - The number to check for primality. + * @returns {boolean} True if n is a prime number, false otherwise. + */ + function isPrime(n) { + if (n < 2) return false // 0 and 1 are not prime numbers + if (n === 2) return true // 2 is a prime number + if (n % 2 === 0) return false // Exclude even numbers + for (let i = 3; i <= Math.sqrt(n); i += 2) { + // Check odd divisors only + if (n % i === 0) return false // Divisible by i, so not prime + } + return true // No divisors found, so it is prime + } + + let maxPrimes = 0 // Store the maximum number of primes found + let product = 0 // Store the product of coefficients a and b + + for (let a = -999; a < 1000; a++) { + for (let b = -1000; b <= 1000; b++) { + let n = 0 + let consecutivePrimes = 0 + while (true) { + const result = n * n + a * n + b // Evaluate the quadratic expression + if (result < 0 || !isPrime(result)) break // Stop if the result is negative or not prime + consecutivePrimes++ + n++ + } + if (consecutivePrimes > maxPrimes) { + maxPrimes = consecutivePrimes + product = a * b // Calculate product of coefficients a and b + } + } + } + + return { maxPrimes, product } // Return the results +} + +// Exporting the main function for use in other modules +export { findMaxConsecutivePrimes } diff --git a/Project-Euler/test/Problem026.test.js b/Project-Euler/test/Problem026.test.js new file mode 100644 index 0000000000..ac276bf748 --- /dev/null +++ b/Project-Euler/test/Problem026.test.js @@ -0,0 +1,30 @@ +import { findLongestRecurringCycle } from '../Problem026' + +/** + * Tests for the findLongestRecurringCycle function. + */ +describe('findLongestRecurringCycle', () => { + // Test to check the basic case with a limit of 10 + test('should return 7 for limit of 10', () => { + const result = findLongestRecurringCycle(10) + expect(result).toBe(7) + }) + + // Test to check with a limit of 1000 + test('should return the correct value for limit of 1000', () => { + const result = findLongestRecurringCycle(1000) + expect(result).toBe(983) // The expected result is the denominator with the longest cycle + }) + + // Test with a smaller limit to validate behavior + test('should return 3 for limit of 4', () => { + const result = findLongestRecurringCycle(4) + expect(result).toBe(3) + }) + + // Test with a limit of 2, where there is no cycle + test('should return 0 for limit of 2', () => { + const result = findLongestRecurringCycle(2) + expect(result).toBe(0) // No cycle for fractions 1/1 and 1/2 + }) +}) diff --git a/Project-Euler/test/Problem027.test.js b/Project-Euler/test/Problem027.test.js new file mode 100644 index 0000000000..f7859f03d6 --- /dev/null +++ b/Project-Euler/test/Problem027.test.js @@ -0,0 +1,9 @@ +import { findMaxConsecutivePrimes } from '../Problem027' + +describe('Problem 027 - Quadratic Primes', () => { + test('should return the correct product of coefficients for max consecutive primes', () => { + const { maxPrimes, product } = findMaxConsecutivePrimes() + expect(maxPrimes).toBe(71) + expect(product).toBe(-59231) + }) +})