The Mathematical Quest: Detecting Arbitrary Sequence Rules
Given a user-provided array of integers such as [2, 7, 16, 29, 46], how can an algorithm automatically deduce whether the sequence is linear, quadratic, cubic, geometric, or recursive? Human mathematicians naturally inspect differences between consecutive terms. In algorithmic terms, this process is formalized through the Method of Finite Differences.
If the first differences between consecutive terms are constant, the sequence is linear (degree 1). If the second differences are constant, it is quadratic (degree 2). If the nth differences become constant, the sequence can be perfectly interpolated by an nth-degree polynomial using Newton's forward difference formula.
Recursive Finite Differences and Polynomial Degree Identification
Our algorithm computes a triangular difference matrix. Starting with the initial sequence row, each subsequent row computes Δa_n = a_(n+1) - a_n. The recurrence continues until either all elements in the row are identical (identifying a polynomial generator) or the row collapses to a single element.
Once a constant difference row is discovered, the algorithm derives the closed-form equation using binomial coefficients, allowing the user to predict the next 50 terms instantaneously.
// Recursive Finite Difference Solver
export interface SequenceAnalysis {
isPolynomial: boolean;
degree: number;
constantDifference?: number;
differences: number[][];
nextTerms: number[];
}
export function analyzeFiniteDifferences(sequence: number[], termsToPredict: number = 3): SequenceAnalysis {
if (sequence.length < 3) throw new Error("At least 3 terms required");
const diffMatrix: number[][] = [sequence];
let currentRow = sequence;
while (currentRow.length > 1) {
const nextRow: number[] = [];
for (let i = 0; i < currentRow.length - 1; i++) {
nextRow.push(currentRow[i + 1] - currentRow[i]);
}
diffMatrix.push(nextRow);
currentRow = nextRow;
// Check if current differences are all identical
const allEqual = currentRow.every((val) => val === currentRow[0]);
if (allEqual) {
const degree = diffMatrix.length - 1;
const constantDiff = currentRow[0];
// Extrapolate next terms forward
const predicted = extrapolateNextTerms(diffMatrix, termsToPredict);
return { isPolynomial: true, degree, constantDifference: constantDiff, differences: diffMatrix, nextTerms: predicted };
}
}
return { isPolynomial: false, degree: -1, differences: diffMatrix, nextTerms: [] };
}
Geometric Progression and Ratio Decomposition
If polynomial difference analysis fails, the solver tests for common ratios. It divides consecutive terms to check for constant multipliers r = a_(n+1) / a_n, identifying exponential progressions like powers of two, tripling series, or fractional attenuations.
If both polynomial and geometric checks yield no constant invariants, the engine checks for alternating signs, Fibonacci-like recurrence relationships (a_n = a_(n-1) + a_(n-2)), and prime indices.
Rendering the Ulam Spiral: Prime Geometry on HTML5 Canvas
Beyond sequence prediction, Number Pattern Analyst visualizes prime numbers on an Ulam Spiral—a rectangular grid where positive integers are written in a counterclockwise spiral starting from 1, and prime numbers are highlighted.
When primes are plotted this way, striking diagonal, horizontal, and vertical lines emerge, visually confirming famous conjectures regarding prime-generating quadratic polynomials like Euler's f(n) = n² + n + 41. Rendering 50,000 spiral cells on canvas with real-time zooming required viewport culling and spatial chunking.
Key Takeaways from the Algorithmic Engine
By executing these mathematical analyses client-side in pure TypeScript, Number Pattern Analyst provides immediate answers without network latency. Mathematical visualization transforms abstract symbols into tangible, exploratory landscapes.