diff --git a/src/helpers/index.ts b/src/helpers/index.ts index 4b0594aa..7f5061b0 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -1,3 +1,6 @@ +type nullable = T | null | undefined; + export { divisors } from './divisors'; export { isPrime } from './prime'; export { isPalindrome } from './isPalindrome'; +export { nullable }; diff --git a/src/problem0004.test.ts b/src/problem0004.test.ts new file mode 100644 index 00000000..1a89ec57 --- /dev/null +++ b/src/problem0004.test.ts @@ -0,0 +1,32 @@ +/** + * Largest palindrome product + * + * https://projecteuler.net/problem=4 + * + * A palindromic number reads the same both ways. + * The largest palindrome made from the product of two 2-digit + * numbers is 9009 = 91 × 99. + * + * Find the largest palindrome made from the product of two 3-digit numbers. + */ + +import logger from './logger'; + +import { problem0004 } from './problem0004'; + +describe('problem 0004', () => { + it('problem 0004 solution found', () => { + expect.assertions(1); + + const solutionFound = 906609; + + const bottom = 111; + const top = 999; + + const calculated = problem0004(bottom, top); + + logger.info(`PROBLEM 0004 solution found: ${calculated}`); + + expect(calculated).toBe(solutionFound); + }); +}); diff --git a/src/problem0004.ts b/src/problem0004.ts new file mode 100644 index 00000000..57480baf --- /dev/null +++ b/src/problem0004.ts @@ -0,0 +1,69 @@ +/** + * Largest palindrome product + * + * https://projecteuler.net/problem=4 + * + * A palindromic number reads the same both ways. + * The largest palindrome made from the product of two 2-digit + * numbers is 9009 = 91 × 99. + * + * Find the largest palindrome made from the product of two 3-digit numbers. + */ + +/// //////////////////////////////////////////////////////////////////////////// +// NOTES ABOUT THE SOLUTION: +// This solution cycles to test all pairs of factors between 111 and 999 that meet the condition of generating a palindrome and saves the largest found. +// I think there must be another optimal solution to avoid testing all cases +// cutting the loop around the largest factor pair +// That's why I thought about doing the loop from highest to lowest. +/// //////////////////////////////////////////////////////////////////////////// + +/// //////////////////////////////////////////////////////////////////////////// + +import logger from './logger'; + +import { nullable, isPalindrome } from './helpers/index'; + +function problem0004(_bottom: number, _top: number): nullable { + let i; + let j; + let foundi; + let foundj; + let foundPalindrome; + + // Find all cases + let cycles = 0; + + i = _top; + while (i >= _bottom) { + j = i; + while (j >= _bottom && (!foundj || j >= foundj)) { + cycles += 1; + + if (isPalindrome(j * i)) { + logger.debug(`FOUND: ${i} x ${j} = ${j * i} is Palindrome`); + + if (!foundPalindrome || i * j > foundPalindrome) { + foundi = i; + foundj = j; + foundPalindrome = i * j; + } + } else { + // console.log(`FOUND: ${i} x ${j} = ${j * i} is NOT Palindrome`); + } + + j -= 1; + } + + i -= 1; + } + + logger.info( + `Problem 0004 Largest Palindrome => ${foundi} 𝗑 ${foundj} = ${foundPalindrome} in ${cycles} cycles` + ); + + return foundPalindrome; +} + +export default problem0004; +export { problem0004 };