javascript
exercises
exercises.js⚡javascript
/**
* ========================================
* 12.1 Array Fundamentals - Exercises
* ========================================
*
* Practice working with JavaScript arrays.
*/
/**
* EXERCISE 1: Create Arrays Different Ways
*
* Create the same array [1, 2, 3, 4, 5] using:
* - Array literal
* - Array.of()
* - Array.from() with length
*
* Verify all three produce the same result.
*/
function exercise1() {
// YOUR CODE HERE:
// const literal = ?
// const arrayOf = ?
// const arrayFrom = ?
// console.log('Literal:', literal);
// console.log('Array.of:', arrayOf);
// console.log('Array.from:', arrayFrom);
}
// exercise1();
/*
* SOLUTION:
*
* function exercise1() {
* const literal = [1, 2, 3, 4, 5];
* const arrayOf = Array.of(1, 2, 3, 4, 5);
* const arrayFrom = Array.from({ length: 5 }, (_, i) => i + 1);
*
* console.log('Literal:', literal);
* console.log('Array.of:', arrayOf);
* console.log('Array.from:', arrayFrom);
*
* // All should show [1, 2, 3, 4, 5]
* }
*/
/**
* EXERCISE 2: Access First, Middle, Last
*
* Given an array, return an object with:
* - first: first element
* - middle: middle element (if even length, choose lower middle)
* - last: last element
*
* Use the .at() method for negative indexing.
*/
function getPositions(arr) {
// YOUR CODE HERE:
// Return { first, middle, last }
}
// console.log(getPositions([1, 2, 3, 4, 5])); // { first: 1, middle: 3, last: 5 }
// console.log(getPositions(['a', 'b', 'c', 'd'])); // { first: 'a', middle: 'b', last: 'd' }
/*
* SOLUTION:
*
* function getPositions(arr) {
* return {
* first: arr.at(0),
* middle: arr[Math.floor((arr.length - 1) / 2)],
* last: arr.at(-1)
* };
* }
*/
/**
* EXERCISE 3: Stack Operations
*
* Implement a simple stack using an array with:
* - push(item): add to top
* - pop(): remove and return from top
* - peek(): view top without removing
* - isEmpty(): check if empty
* - size(): return number of items
*/
function createStack() {
// YOUR CODE HERE:
// Return object with push, pop, peek, isEmpty, size methods
}
// const stack = createStack();
// stack.push('a');
// stack.push('b');
// console.log(stack.peek()); // 'b'
// console.log(stack.pop()); // 'b'
// console.log(stack.size()); // 1
/*
* SOLUTION:
*
* function createStack() {
* const items = [];
* return {
* push(item) { items.push(item); },
* pop() { return items.pop(); },
* peek() { return items.at(-1); },
* isEmpty() { return items.length === 0; },
* size() { return items.length; }
* };
* }
*/
/**
* EXERCISE 4: Queue Operations
*
* Implement a queue (FIFO) using an array with:
* - enqueue(item): add to back
* - dequeue(): remove and return from front
* - front(): view front without removing
* - isEmpty(): check if empty
* - size(): return number of items
*/
function createQueue() {
// YOUR CODE HERE:
// Return object with enqueue, dequeue, front, isEmpty, size methods
}
// const queue = createQueue();
// queue.enqueue('first');
// queue.enqueue('second');
// console.log(queue.front()); // 'first'
// console.log(queue.dequeue()); // 'first'
// console.log(queue.size()); // 1
/*
* SOLUTION:
*
* function createQueue() {
* const items = [];
* return {
* enqueue(item) { items.push(item); },
* dequeue() { return items.shift(); },
* front() { return items.at(0); },
* isEmpty() { return items.length === 0; },
* size() { return items.length; }
* };
* }
*/
/**
* EXERCISE 5: Insert At Index
*
* Write a function that inserts an element at a specific index
* without mutating the original array.
* If index is out of bounds, add to end.
*/
function insertAt(arr, index, element) {
// YOUR CODE HERE:
// Return new array with element inserted at index
}
// console.log(insertAt([1, 2, 4, 5], 2, 3)); // [1, 2, 3, 4, 5]
// console.log(insertAt([1, 2, 3], 0, 0)); // [0, 1, 2, 3]
// console.log(insertAt([1, 2, 3], 10, 4)); // [1, 2, 3, 4]
/*
* SOLUTION:
*
* function insertAt(arr, index, element) {
* if (index >= arr.length) {
* return [...arr, element];
* }
* return [...arr.slice(0, index), element, ...arr.slice(index)];
* }
*/
/**
* EXERCISE 6: Remove At Index
*
* Write a function that removes an element at a specific index
* without mutating the original array.
* If index is out of bounds, return copy of original.
*/
function removeAt(arr, index) {
// YOUR CODE HERE:
// Return new array with element at index removed
}
// console.log(removeAt([1, 2, 3, 4, 5], 2)); // [1, 2, 4, 5]
// console.log(removeAt([1, 2, 3], 0)); // [2, 3]
// console.log(removeAt([1, 2, 3], 10)); // [1, 2, 3]
/*
* SOLUTION:
*
* function removeAt(arr, index) {
* if (index < 0 || index >= arr.length) {
* return [...arr];
* }
* return [...arr.slice(0, index), ...arr.slice(index + 1)];
* }
*/
/**
* EXERCISE 7: Map - Double and Square
*
* Given an array of numbers:
* - doubleAll: double each number
* - squareAll: square each number
* - doubleEvenSquareOdd: double evens, square odds
*/
function arrayOperations(numbers) {
// YOUR CODE HERE:
// Return { doubleAll, squareAll, doubleEvenSquareOdd }
}
// const nums = [1, 2, 3, 4, 5];
// const result = arrayOperations(nums);
// console.log(result.doubleAll); // [2, 4, 6, 8, 10]
// console.log(result.squareAll); // [1, 4, 9, 16, 25]
// console.log(result.doubleEvenSquareOdd); // [1, 4, 9, 8, 25]
/*
* SOLUTION:
*
* function arrayOperations(numbers) {
* return {
* doubleAll: numbers.map(n => n * 2),
* squareAll: numbers.map(n => n ** 2),
* doubleEvenSquareOdd: numbers.map(n => n % 2 === 0 ? n * 2 : n ** 2)
* };
* }
*/
/**
* EXERCISE 8: Filter Complex Conditions
*
* Given an array of products, create functions to filter:
* - inStock: products where inStock is true
* - affordable: products with price < 50
* - available: products that are inStock AND price < 100
*/
function filterProducts(products) {
// YOUR CODE HERE:
// Return { inStock, affordable, available }
}
// const products = [
// { name: 'Phone', price: 699, inStock: true },
// { name: 'Cable', price: 19, inStock: true },
// { name: 'Case', price: 29, inStock: false },
// { name: 'Earbuds', price: 89, inStock: true }
// ];
// const filtered = filterProducts(products);
// console.log(filtered.inStock.map(p => p.name)); // ['Phone', 'Cable', 'Earbuds']
// console.log(filtered.affordable.map(p => p.name)); // ['Cable', 'Case']
// console.log(filtered.available.map(p => p.name)); // ['Cable', 'Earbuds']
/*
* SOLUTION:
*
* function filterProducts(products) {
* return {
* inStock: products.filter(p => p.inStock),
* affordable: products.filter(p => p.price < 50),
* available: products.filter(p => p.inStock && p.price < 100)
* };
* }
*/
/**
* EXERCISE 9: Reduce - Statistics
*
* Calculate statistics for an array of numbers:
* - sum: total of all numbers
* - average: mean value
* - min: smallest number
* - max: largest number
*/
function calculateStats(numbers) {
// YOUR CODE HERE:
// Return { sum, average, min, max }
}
// console.log(calculateStats([10, 20, 30, 40, 50]));
// { sum: 150, average: 30, min: 10, max: 50 }
/*
* SOLUTION:
*
* function calculateStats(numbers) {
* if (numbers.length === 0) return { sum: 0, average: 0, min: undefined, max: undefined };
*
* const sum = numbers.reduce((acc, n) => acc + n, 0);
* return {
* sum,
* average: sum / numbers.length,
* min: numbers.reduce((a, b) => Math.min(a, b)),
* max: numbers.reduce((a, b) => Math.max(a, b))
* };
* }
*/
/**
* EXERCISE 10: Reduce - Group By
*
* Group an array of objects by a specific property.
*/
function groupBy(array, property) {
// YOUR CODE HERE:
// Return object with keys as property values, values as arrays
}
// const people = [
// { name: 'John', department: 'Sales' },
// { name: 'Jane', department: 'Engineering' },
// { name: 'Bob', department: 'Sales' },
// { name: 'Alice', department: 'Engineering' }
// ];
// console.log(groupBy(people, 'department'));
// {
// Sales: [{ name: 'John', ... }, { name: 'Bob', ... }],
// Engineering: [{ name: 'Jane', ... }, { name: 'Alice', ... }]
// }
/*
* SOLUTION:
*
* function groupBy(array, property) {
* return array.reduce((acc, item) => {
* const key = item[property];
* (acc[key] = acc[key] || []).push(item);
* return acc;
* }, {});
* }
*/
/**
* EXERCISE 11: Find and Validate
*
* Given an array of users:
* - findByEmail: find user by email (case-insensitive)
* - hasAdmin: check if any user has role 'admin'
* - allVerified: check if all users are verified
*/
function userOperations(users) {
// YOUR CODE HERE:
// Return { findByEmail, hasAdmin, allVerified }
}
// const users = [
// { name: 'John', email: 'John@test.com', role: 'user', verified: true },
// { name: 'Jane', email: 'jane@test.com', role: 'admin', verified: true },
// { name: 'Bob', email: 'bob@test.com', role: 'user', verified: false }
// ];
// const ops = userOperations(users);
// console.log(ops.findByEmail('JOHN@TEST.COM')); // { name: 'John', ... }
// console.log(ops.hasAdmin); // true
// console.log(ops.allVerified); // false
/*
* SOLUTION:
*
* function userOperations(users) {
* return {
* findByEmail(email) {
* return users.find(u =>
* u.email.toLowerCase() === email.toLowerCase()
* );
* },
* hasAdmin: users.some(u => u.role === 'admin'),
* allVerified: users.every(u => u.verified)
* };
* }
*/
/**
* EXERCISE 12: Array Transformation Pipeline
*
* Create a function that processes orders:
* 1. Filter only completed orders
* 2. Extract total amounts
* 3. Calculate grand total and average
*/
function processOrders(orders) {
// YOUR CODE HERE:
// Return { completedCount, grandTotal, averageOrder }
}
// const orders = [
// { id: 1, status: 'completed', total: 100 },
// { id: 2, status: 'pending', total: 50 },
// { id: 3, status: 'completed', total: 200 },
// { id: 4, status: 'cancelled', total: 75 },
// { id: 5, status: 'completed', total: 150 }
// ];
// console.log(processOrders(orders));
// { completedCount: 3, grandTotal: 450, averageOrder: 150 }
/*
* SOLUTION:
*
* function processOrders(orders) {
* const completed = orders.filter(o => o.status === 'completed');
* const totals = completed.map(o => o.total);
* const grandTotal = totals.reduce((sum, t) => sum + t, 0);
*
* return {
* completedCount: completed.length,
* grandTotal,
* averageOrder: completed.length > 0 ? grandTotal / completed.length : 0
* };
* }
*/
/**
* EXERCISE 13: Flatten and Extract
*
* Given nested data, flatten and extract specific values:
* - flattenCategories: flatten all product names
* - getTotalProducts: count all products
* - getCategoriesWithProducts: categories with product count
*/
function analyzeCategories(categories) {
// YOUR CODE HERE:
// Return { allProductNames, totalProducts, categoriesWithCounts }
}
// const categories = [
// { name: 'Electronics', products: ['Phone', 'Laptop', 'Tablet'] },
// { name: 'Clothing', products: ['Shirt', 'Pants'] },
// { name: 'Books', products: ['Novel', 'Textbook', 'Magazine'] }
// ];
// const analysis = analyzeCategories(categories);
// console.log(analysis.allProductNames);
// ['Phone', 'Laptop', 'Tablet', 'Shirt', 'Pants', 'Novel', 'Textbook', 'Magazine']
// console.log(analysis.totalProducts); // 8
// console.log(analysis.categoriesWithCounts);
// [{ name: 'Electronics', count: 3 }, ...]
/*
* SOLUTION:
*
* function analyzeCategories(categories) {
* return {
* allProductNames: categories.flatMap(c => c.products),
* totalProducts: categories.reduce((sum, c) => sum + c.products.length, 0),
* categoriesWithCounts: categories.map(c => ({
* name: c.name,
* count: c.products.length
* }))
* };
* }
*/
/**
* EXERCISE 14: Sort Complex Data
*
* Sort an array of students by multiple criteria:
* - byGrade: descending by grade
* - byName: alphabetically by name
* - byGradeThenName: by grade desc, then name asc
*/
function sortStudents(students) {
// YOUR CODE HERE:
// Return { byGrade, byName, byGradeThenName }
}
// const students = [
// { name: 'Charlie', grade: 85 },
// { name: 'Alice', grade: 92 },
// { name: 'Bob', grade: 85 },
// { name: 'Diana', grade: 78 }
// ];
// const sorted = sortStudents(students);
// console.log(sorted.byGrade.map(s => s.name));
// ['Alice', 'Charlie', 'Bob', 'Diana']
// console.log(sorted.byGradeThenName.map(s => s.name));
// ['Alice', 'Bob', 'Charlie', 'Diana']
/*
* SOLUTION:
*
* function sortStudents(students) {
* return {
* byGrade: [...students].sort((a, b) => b.grade - a.grade),
* byName: [...students].sort((a, b) => a.name.localeCompare(b.name)),
* byGradeThenName: [...students].sort((a, b) => {
* if (b.grade !== a.grade) return b.grade - a.grade;
* return a.name.localeCompare(b.name);
* })
* };
* }
*/
/**
* EXERCISE 15: Remove Duplicates
*
* Create functions to remove duplicates:
* - removeDuplicates: from array of primitives
* - removeDuplicatesByKey: from array of objects using key
*/
function removeDuplicates(arr) {
// YOUR CODE HERE:
// Return array with duplicates removed
}
function removeDuplicatesByKey(arr, key) {
// YOUR CODE HERE:
// Return array with duplicates by key removed (keep first)
}
// console.log(removeDuplicates([1, 2, 2, 3, 3, 3, 4])); // [1, 2, 3, 4]
// console.log(removeDuplicates(['a', 'b', 'a', 'c', 'b'])); // ['a', 'b', 'c']
// const items = [
// { id: 1, name: 'Apple' },
// { id: 2, name: 'Banana' },
// { id: 1, name: 'Apple Updated' },
// { id: 3, name: 'Cherry' }
// ];
// console.log(removeDuplicatesByKey(items, 'id'));
// [{ id: 1, name: 'Apple' }, { id: 2, name: 'Banana' }, { id: 3, name: 'Cherry' }]
/*
* SOLUTION:
*
* function removeDuplicates(arr) {
* return [...new Set(arr)];
* }
*
* function removeDuplicatesByKey(arr, key) {
* const seen = new Set();
* return arr.filter(item => {
* if (seen.has(item[key])) return false;
* seen.add(item[key]);
* return true;
* });
* }
*/
/**
* EXERCISE 16: Array Chunking
*
* Split an array into chunks of specified size.
*/
function chunkArray(arr, size) {
// YOUR CODE HERE:
// Return array of arrays, each with 'size' elements
}
// console.log(chunkArray([1, 2, 3, 4, 5, 6, 7], 3));
// [[1, 2, 3], [4, 5, 6], [7]]
// console.log(chunkArray([1, 2, 3, 4], 2));
// [[1, 2], [3, 4]]
/*
* SOLUTION:
*
* function chunkArray(arr, size) {
* return Array.from(
* { length: Math.ceil(arr.length / size) },
* (_, i) => arr.slice(i * size, i * size + size)
* );
* }
*
* // Alternative with reduce:
* function chunkArray(arr, size) {
* return arr.reduce((chunks, item, i) => {
* if (i % size === 0) chunks.push([]);
* chunks[chunks.length - 1].push(item);
* return chunks;
* }, []);
* }
*/
/**
* EXERCISE 17: Array Intersection and Difference
*
* Create functions for set-like operations:
* - intersection: elements in both arrays
* - difference: elements in first but not second
* - union: elements in either array (no duplicates)
*/
function setOperations(arr1, arr2) {
// YOUR CODE HERE:
// Return { intersection, difference, union }
}
// console.log(setOperations([1, 2, 3, 4], [3, 4, 5, 6]));
// {
// intersection: [3, 4],
// difference: [1, 2],
// union: [1, 2, 3, 4, 5, 6]
// }
/*
* SOLUTION:
*
* function setOperations(arr1, arr2) {
* const set1 = new Set(arr1);
* const set2 = new Set(arr2);
*
* return {
* intersection: arr1.filter(x => set2.has(x)),
* difference: arr1.filter(x => !set2.has(x)),
* union: [...new Set([...arr1, ...arr2])]
* };
* }
*/
/**
* EXERCISE 18: Zip Arrays
*
* Combine multiple arrays element by element.
*/
function zip(...arrays) {
// YOUR CODE HERE:
// Return array of arrays, each containing elements at same index
}
// console.log(zip([1, 2, 3], ['a', 'b', 'c']));
// [[1, 'a'], [2, 'b'], [3, 'c']]
// console.log(zip([1, 2], ['a', 'b'], ['x', 'y']));
// [[1, 'a', 'x'], [2, 'b', 'y']]
/*
* SOLUTION:
*
* function zip(...arrays) {
* const minLength = Math.min(...arrays.map(a => a.length));
* return Array.from({ length: minLength }, (_, i) =>
* arrays.map(arr => arr[i])
* );
* }
*/
/**
* EXERCISE 19: Rotate Array
*
* Rotate array elements by n positions:
* - Positive n: rotate right
* - Negative n: rotate left
*/
function rotateArray(arr, n) {
// YOUR CODE HERE:
// Return new rotated array
}
// console.log(rotateArray([1, 2, 3, 4, 5], 2)); // [4, 5, 1, 2, 3]
// console.log(rotateArray([1, 2, 3, 4, 5], -2)); // [3, 4, 5, 1, 2]
// console.log(rotateArray([1, 2, 3], 0)); // [1, 2, 3]
/*
* SOLUTION:
*
* function rotateArray(arr, n) {
* const len = arr.length;
* if (len === 0) return [...arr];
*
* // Normalize n to be within array bounds
* const rotation = ((n % len) + len) % len;
*
* return [...arr.slice(-rotation), ...arr.slice(0, -rotation || len)];
* }
*/
/**
* EXERCISE 20: Deep Flatten
*
* Flatten an array of any nesting depth.
* Do NOT use Array.flat().
*/
function deepFlatten(arr) {
// YOUR CODE HERE:
// Return completely flattened array
}
// console.log(deepFlatten([1, [2, [3, [4, [5]]]]])); // [1, 2, 3, 4, 5]
// console.log(deepFlatten([[[[1]]], [[[2]]]])); // [1, 2]
/*
* SOLUTION:
*
* function deepFlatten(arr) {
* return arr.reduce((flat, item) =>
* flat.concat(Array.isArray(item) ? deepFlatten(item) : item),
* []
* );
* }
*
* // Alternative with recursion:
* function deepFlatten(arr) {
* const result = [];
* for (const item of arr) {
* if (Array.isArray(item)) {
* result.push(...deepFlatten(item));
* } else {
* result.push(item);
* }
* }
* return result;
* }
*/
/**
* BONUS EXERCISE 21: Partition
*
* Split array into two based on predicate:
* - First array: elements that pass
* - Second array: elements that fail
*/
function partition(arr, predicate) {
// YOUR CODE HERE:
// Return [passing, failing]
}
// const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// console.log(partition(nums, n => n % 2 === 0));
// [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
/*
* SOLUTION:
*
* function partition(arr, predicate) {
* return arr.reduce(
* ([pass, fail], item) =>
* predicate(item) ? [[...pass, item], fail] : [pass, [...fail, item]],
* [[], []]
* );
* }
*
* // Alternative clearer version:
* function partition(arr, predicate) {
* const pass = [];
* const fail = [];
* for (const item of arr) {
* (predicate(item) ? pass : fail).push(item);
* }
* return [pass, fail];
* }
*/
/**
* BONUS EXERCISE 22: Frequency Counter
*
* Count frequency of each unique element.
* Return sorted by frequency (descending).
*/
function frequencyCounter(arr) {
// YOUR CODE HERE:
// Return array of [element, count] pairs sorted by count
}
// console.log(frequencyCounter(['a', 'b', 'a', 'c', 'a', 'b']));
// [['a', 3], ['b', 2], ['c', 1]]
/*
* SOLUTION:
*
* function frequencyCounter(arr) {
* const counts = arr.reduce((acc, item) => {
* acc[item] = (acc[item] || 0) + 1;
* return acc;
* }, {});
*
* return Object.entries(counts)
* .sort((a, b) => b[1] - a[1]);
* }
*/
console.log('Array exercises loaded! Uncomment tests to practice.');