-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
feat: add findLongestRecurringCycle algorithm #1733
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
abda-gaye
wants to merge
3
commits into
TheAlgorithms:master
Choose a base branch
from
abda-gaye:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
}) | ||
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}) | ||
}) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.