Loops are the engine of programming — they let you process data, search for answers, and automate repetitive tasks. This tutorial covers fundamental algorithmic problems that specifically exercise your loop skills. Mastering these problems will prepare you for more complex challenges in data structures, algorithms, and real-world backend development.
Before writing any loop, ask yourself:
- What am I iterating over? — A range of numbers? An array? Until a condition is met?
- What do I need to track? — A running sum? A maximum value? A counter?
- When do I stop? — Fixed count? Specific condition? End of data?
- What do I return? — A single value? A collection? A modified structure?
Problem: Calculate the sum of numbers from 1 to N.
function sumToN(n) {
let sum = 0;
for (let i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
console.log(sumToN(5)); // 15 (1+2+3+4+5)
console.log(sumToN(10)); // 55Mathematical shortcut: n * (n + 1) / 2
function sumToNFast(n) {
return (n * (n + 1)) / 2;
}Problem: Calculate n! = n × (n-1) × (n-2) × ... × 1
function factorial(n) {
if (n < 0) return undefined;
if (n === 0 || n === 1) return 1;
let result = 1;
for (let i = 2; i <= n; i++) {
result *= i;
}
return result;
}
console.log(factorial(5)); // 120
console.log(factorial(0)); // 1
console.log(factorial(10)); // 3628800Problem: A prime number is only divisible by 1 and itself.
function isPrime(n) {
if (n <= 1) return false;
if (n <= 3) return true;
if (n % 2 === 0 || n % 3 === 0) return false;
// Check up to square root only
for (let i = 5; i * i <= n; i += 6) {
if (n % i === 0 || n % (i + 2) === 0) {
return false;
}
}
return true;
}
console.log(isPrime(2)); // true
console.log(isPrime(17)); // true
console.log(isPrime(18)); // false
console.log(isPrime(97)); // trueOptimization: Only check up to √n. If n has a factor larger than √n, the corresponding pair factor must be smaller than √n.
function primesInRange(start, end) {
const primes = [];
for (let num = start; num <= end; num++) {
if (isPrime(num)) {
primes.push(num);
}
}
return primes;
}
console.log(primesInRange(1, 50));
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]Problem: Generate the first N Fibonacci numbers: 0, 1, 1, 2, 3, 5, 8, 13...
function fibonacci(n) {
if (n <= 0) return [];
if (n === 1) return [0];
const series = [0, 1];
for (let i = 2; i < n; i++) {
series.push(series[i - 1] + series[i - 2]);
}
return series;
}
console.log(fibonacci(10));
// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]function nthFibonacci(n) {
if (n <= 0) return 0;
if (n === 1) return 1;
let prev = 0;
let curr = 1;
for (let i = 2; i <= n; i++) {
const next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
console.log(nthFibonacci(10)); // 55Problem: Reverse the digits of a number.
function reverseNumber(num) {
let reversed = 0;
let n = Math.abs(num);
while (n > 0) {
const digit = n % 10;
reversed = reversed * 10 + digit;
n = Math.floor(n / 10);
}
return num < 0 ? -reversed : reversed;
}
console.log(reverseNumber(12345)); // 54321
console.log(reverseNumber(-987)); // -789
console.log(reverseNumber(1200)); // 21Problem: A palindrome reads the same forwards and backwards.
function isPalindromeNumber(num) {
if (num < 0) return false;
let reversed = 0;
let original = num;
while (num > 0) {
reversed = reversed * 10 + (num % 10);
num = Math.floor(num / 10);
}
return original === reversed;
}
console.log(isPalindromeNumber(121)); // true
console.log(isPalindromeNumber(123)); // false
console.log(isPalindromeNumber(12321)); // truefunction countDigits(num) {
if (num === 0) return 1;
let count = 0;
n = Math.abs(num);
while (n > 0) {
count++;
n = Math.floor(n / 10);
}
return count;
}
console.log(countDigits(12345)); // 5
console.log(countDigits(0)); // 1
console.log(countDigits(-999)); // 3Problem: A number equal to the sum of its digits raised to the power of the number of digits.
function isArmstrong(num) {
const digits = String(num).split("").map(Number);
const power = digits.length;
let sum = 0;
for (const digit of digits) {
sum += Math.pow(digit, power);
}
return sum === num;
}
console.log(isArmstrong(153)); // true (1³ + 5³ + 3³ = 1 + 125 + 27 = 153)
console.log(isArmstrong(9474)); // true
console.log(isArmstrong(123)); // falseProblem: Find the largest number that divides both numbers.
function gcd(a, b) {
while (b !== 0) {
const temp = b;
b = a % b;
a = temp;
}
return a;
}
console.log(gcd(48, 18)); // 6
console.log(gcd(56, 98)); // 14function lcm(a, b) {
return (a * b) / gcd(a, b);
}
console.log(lcm(4, 6)); // 12function sumOfDigits(num) {
let sum = 0;
let n = Math.abs(num);
while (n > 0) {
sum += n % 10;
n = Math.floor(n / 10);
}
return sum;
}
console.log(sumOfDigits(12345)); // 15
console.log(sumOfDigits(999)); // 27function toBinary(num) {
if (num === 0) return "0";
let binary = "";
let n = num;
while (n > 0) {
binary = (n % 2) + binary;
n = Math.floor(n / 2);
}
return binary;
}
console.log(toBinary(10)); // "1010"
console.log(toBinary(255)); // "11111111"Problem: A number equal to the sum of its proper divisors (excluding itself).
function isPerfect(num) {
if (num <= 1) return false;
let sum = 1; // 1 is always a divisor
for (let i = 2; i * i <= num; i++) {
if (num % i === 0) {
sum += i;
if (i !== num / i) {
sum += num / i;
}
}
}
return sum === num;
}
console.log(isPerfect(6)); // true (1 + 2 + 3 = 6)
console.log(isPerfect(28)); // true (1 + 2 + 4 + 7 + 14 = 28)
console.log(isPerfect(12)); // falsefunction power(base, exponent) {
if (exponent === 0) return 1;
if (exponent < 0) return 1 / power(base, -exponent);
let result = 1;
for (let i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
console.log(power(2, 10)); // 1024
console.log(power(5, 0)); // 1
console.log(power(2, -3)); // 0.125Problem: Start with any positive integer n. If n is even, divide by 2. If odd, multiply by 3 and add 1. Repeat until you reach 1.
function collatzSequence(n) {
const sequence = [n];
while (n !== 1) {
if (n % 2 === 0) {
n = n / 2;
} else {
n = 3 * n + 1;
}
sequence.push(n);
}
return sequence;
}
console.log(collatzSequence(6));
// [6, 3, 10, 5, 16, 8, 4, 2, 1]Problem: Find all primes up to N efficiently.
function sieveOfEratosthenes(n) {
const isPrime = new Array(n + 1).fill(true);
isPrime[0] = isPrime[1] = false;
for (let i = 2; i * i <= n; i++) {
if (isPrime[i]) {
for (let j = i * i; j <= n; j += i) {
isPrime[j] = false;
}
}
}
const primes = [];
for (let i = 2; i <= n; i++) {
if (isPrime[i]) primes.push(i);
}
return primes;
}
console.log(sieveOfEratosthenes(50));
// [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]| Pattern | Technique | Example |
|---|---|---|
| Running total | Accumulate in a variable | Sum, product |
| Find max/min | Compare each element | Largest, smallest |
| Digit extraction | % 10 and / 10 |
Reverse, palindrome |
| Range iteration | Fixed for loop |
Factorial, sum |
| Conditional iteration | while with condition |
GCD, Collatz |
| Nested iteration | Loop inside loop | Primes in range |
| Boolean flag | Track state | Prime check |
A strong number equals the sum of the factorial of its digits.
console.log(isStrong(145)); // true (1! + 4! + 5! = 1 + 24 + 120 = 145)A number divisible by the sum of its digits.
console.log(isHarshad(18)); // true (1+8=9, 18%9===0)Convert a decimal number to any base (2-16).
console.log(toBase(255, 16)); // "FF"
console.log(toBase(10, 2)); // "1010"Count trailing zeros in n! without calculating the factorial.
console.log(trailingZeros(100)); // 24Calculate square root without using Math.sqrt().
console.log(squareRoot(25)); // 5
console.log(squareRoot(2)); // ~1.414- Loops are essential for iteration, accumulation, and search
- Always look for mathematical optimizations (e.g., √n for primes)
- Digit manipulation uses
% 10(last digit) and/ 10(remove last digit) - Running totals and comparisons are the most common loop patterns
- Practice converting problems into step-by-step algorithms
- Test with edge cases: 0, 1, negative numbers, large inputs
Build on these fundamentals with:
- Arrays — working with collections of data
- Functions — organizing code into reusable blocks
- Object-Oriented JavaScript — structuring larger programs
Happy coding! 🚀