euler(14): longest collatz sequence

This commit is contained in:
newt 2024-10-09 18:02:37 +01:00
parent a636726cb7
commit 6a9e214501
4 changed files with 95 additions and 27 deletions

12
.vscode/settings.json vendored
View file

@ -1,3 +1,13 @@
{ {
"java.project.sourcePaths": ["java"] "java.project.sourcePaths": ["java"],
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true,
"euler/node_modules": true,
"euler/python_archive": true
}
} }

View file

@ -2,7 +2,7 @@
"name": "project-euler", "name": "project-euler",
"scripts": { "scripts": {
"build": "gulp build", "build": "gulp build",
"start": "node run" "start": "node run.js"
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^16.11.6", "@types/node": "^16.11.6",

View file

@ -1,8 +1,10 @@
const fs = require('fs'); const fs = require('fs');
const chalk = require('chalk'); const chalk = require('chalk');
const { spawnSync } = require('child_process'); const { spawnSync, spawn } = require('child_process');
const perf = require('execution-time')(); const perf = require('execution-time')();
// todo: move to ts-node
const run = (file, puzzleName) => { const run = (file, puzzleName) => {
// Calculate the length of the divider for the puzzle // Calculate the length of the divider for the puzzle
let divider = '--'; let divider = '--';
@ -26,17 +28,32 @@ const run = (file, puzzleName) => {
console.log(chalk.bold(chalk.yellow(`Executed in ${results.words}`))); console.log(chalk.bold(chalk.yellow(`Executed in ${results.words}`)));
}; };
// Get files new Promise(async resolve => {
const tsFiles = fs // Rebuild the files
const gulp = spawn('npx', ['gulp-cli', 'build'], { shell: true, stdio: 'pipe' });
gulp.stdout.on('data', data => {
const message = data.toString();
const match = message.match(/Starting '(.*)'/)?.[1];
if (match) console.log(chalk.red(`[gulp] Running '${match}' task`));
});
gulp.on('close', () => {
console.log();
resolve();
});
}).then(() => {
// Get files
const tsFiles = fs
.readdirSync('src') .readdirSync('src')
.filter(f => f.endsWith('.ts')) .filter(f => f.endsWith('.ts'))
.filter(f => f !== 'utils.ts'); .filter(f => f !== 'utils.ts');
const jsFiles = fs const jsFiles = fs
.readdirSync('build') .readdirSync('build')
.filter(f => f.endsWith('.js')) .filter(f => f.endsWith('.js'))
.filter(f => f !== 'utils.js'); .filter(f => f !== 'utils.js');
try { try {
// Extract the puzzle number // Extract the puzzle number
const puzzleNumber = process.argv[2]; const puzzleNumber = process.argv[2];
if (isNaN(puzzleNumber)) throw Error(); if (isNaN(puzzleNumber)) throw Error();
@ -46,7 +63,7 @@ try {
const puzzleName = tsFile.split('.ts')[0]; const puzzleName = tsFile.split('.ts')[0];
run(`${puzzleNumber}.js`, puzzleName); run(`${puzzleNumber}.js`, puzzleName);
} catch (error) { } catch (error) {
for (let i = 0; i < jsFiles.length; i++) { for (let i = 0; i < jsFiles.length; i++) {
const file = jsFiles[i]; const file = jsFiles[i];
const tsFile = tsFiles[i]; const tsFile = tsFiles[i];
@ -55,4 +72,5 @@ try {
run(file, puzzleName); run(file, puzzleName);
console.log(); console.log();
} }
} }
});

View file

@ -0,0 +1,40 @@
// n -> n/2 (if n is even)
// n -> 3n + 1 (if n is odd)
// Start at a number, iterate until 1
// Which starting number under one million has the longest chain?
export {};
const isEven = (n: number) => n % 2 === 0;
const collatzSequence = (startNumber: number) => {
let currentNumber = startNumber;
let sequence = [startNumber];
while (currentNumber > 1) {
if (isEven(currentNumber)) currentNumber = currentNumber / 2;
else currentNumber = currentNumber * 3 + 1;
sequence.push(currentNumber);
}
return sequence;
};
const longestCollatzUnderLimit = (limit: number) => {
let longestStartingNumber = -1;
let longestStartingNumberLength = -1;
for (let i = 1; i < limit; i++) {
const sequence = collatzSequence(i);
if (sequence.length > longestStartingNumberLength) {
longestStartingNumber = i;
longestStartingNumberLength = sequence.length;
}
}
return longestStartingNumberLength;
};
console.log(longestCollatzUnderLimit(1000000));