javascript

exercises

exercises.js
/**
 * 8.3 BigInt - Exercises
 */

/**
 * Exercise 1: BigInt Creation
 * Create BigInt values in different ways
 */
function createBigInts() {
  // TODO: Create and return an object with:
  // - literal: BigInt literal for 9007199254740993
  // - fromNumber: BigInt from the number 1000
  // - fromString: BigInt from string "123456789012345678901234567890"
  // - fromHex: BigInt from hex string "0xFFFFFFFFFFFFFFFF"
  // - negative: Negative BigInt literal for -9007199254740993

  return {
    // Your code here
  };
}

// Test:
// const bigInts = createBigInts();
// console.log(bigInts.literal === 9007199254740993n);

/**
 * Exercise 2: Safe Arithmetic
 * Perform operations that would overflow with Number
 */
function safeLargeMultiply(a, b) {
  // TODO: Multiply two large numbers safely using BigInt
  // Parameters can be number or string
  // Return result as string
}

// Test:
// console.log(safeLargeMultiply("9007199254740991", "9007199254740991"));

/**
 * Exercise 3: Factorial with BigInt
 * Calculate factorial of large numbers
 */
function bigFactorial(n) {
  // TODO: Calculate n! using BigInt
  // Return the BigInt result
}

// Test:
// console.log(bigFactorial(50));  // Should be exact, not exponential notation
// console.log(bigFactorial(100).toString().length);  // 158 digits

/**
 * Exercise 4: Power of Two
 * Work with large powers
 */
function powerOfTwo(exponent) {
  // TODO: Calculate 2^exponent using BigInt
  // Return { value: BigInt, digits: number }
}

// Test:
// const p = powerOfTwo(1000);
// console.log(p.digits);  // 302

/**
 * Exercise 5: Type Conversion Helper
 * Create utilities for BigInt conversion
 */
const bigIntUtils = {
  // TODO: Implement these methods:
  // fromNumber(n): Safely convert number to BigInt
  // Throw error if not safe integer
  // toNumber(big): Convert BigInt to number
  // Throw error if would lose precision
  // toString(big, radix): Convert to string with radix
  // fromJSON(str): Parse BigInt from JSON-safe string format
  // toJSON(big): Convert BigInt to JSON-safe format
};

// Test:
// console.log(bigIntUtils.fromNumber(123)); // 123n
// console.log(bigIntUtils.toNumber(123n));  // 123

/**
 * Exercise 6: BigInt Comparison
 * Compare and sort BigInt values
 */
function sortBigInts(arr) {
  // TODO: Sort array of BigInt values in ascending order
  // Handle both BigInt and string representations
}

function findMinMax(arr) {
  // TODO: Find min and max in array of BigInts
  // Return { min: BigInt, max: BigInt }
}

// Test:
// const arr = [100n, 5n, 9999999999999999999999n, 42n];
// console.log(sortBigInts(arr));

/**
 * Exercise 7: Binary Operations
 * Perform bitwise operations with BigInt
 */
function bitwiseOperations(a, b) {
  // TODO: Return object with all bitwise operations
  // - and, or, xor, not_a, not_b
  // - leftShift (a << 2), rightShift (a >> 2)
}

function countBits(n) {
  // TODO: Count number of 1 bits in BigInt
}

// Test:
// console.log(countBits(255n));  // 8

/**
 * Exercise 8: Financial Calculator
 * Precise financial calculations with BigInt
 */
class PreciseMoney {
  // TODO: Implement money class using BigInt cents
  // constructor(dollars, cents) or constructor(totalCents)
  // add(other): PreciseMoney
  // subtract(other): PreciseMoney
  // multiply(factor): PreciseMoney
  // divide(divisor): PreciseMoney
  // format(): string like "$1,234.56"
  // static parse(str): PreciseMoney from string like "$1,234.56"
}

// Test:
// const price = new PreciseMoney(99, 99);
// const total = price.multiply(1000000);
// console.log(total.format());  // "$99,990,000.00"

/**
 * Exercise 9: Snowflake ID Generator
 * Generate Twitter-style snowflake IDs
 */
class SnowflakeGenerator {
  // TODO: Implement snowflake ID generator
  // Format: timestamp (42 bits) | worker (5 bits) | process (5 bits) | sequence (12 bits)
  // constructor(workerId, processId)
  // generate(): BigInt - generate next ID
  // parse(id): { timestamp, workerId, processId, sequence }
  // static EPOCH: BigInt - custom epoch (e.g., 2020-01-01)
}

// Test:
// const gen = new SnowflakeGenerator(1, 1);
// const id1 = gen.generate();
// const id2 = gen.generate();
// console.log(id1 < id2);  // true

/**
 * Exercise 10: Arbitrary Precision Math
 * Implement mathematical functions for BigInt
 */
const bigMath = {
  // TODO: Implement these functions
  // sqrt(n): Integer square root (floor)
  // gcd(a, b): Greatest common divisor
  // lcm(a, b): Least common multiple
  // modPow(base, exp, mod): Modular exponentiation
  // isPrime(n): Check if prime (simple method ok)
  // fibonacci(n): nth Fibonacci number
};

// Test:
// console.log(bigMath.sqrt(100n));  // 10n
// console.log(bigMath.gcd(48n, 18n));  // 6n
// console.log(bigMath.fibonacci(100));  // 354224848179261915075n

/**
 * BONUS CHALLENGES
 */

/**
 * Bonus 1: BigInt Range Iterator
 * Create an iterator for BigInt ranges
 */
function* bigIntRange(start, end, step = 1n) {
  // TODO: Yield BigInt values from start to end (exclusive)
  // Handle both positive and negative steps
}

// Test:
// for (const n of bigIntRange(0n, 10n, 2n)) {
//     console.log(n);  // 0n, 2n, 4n, 6n, 8n
// }

/**
 * Bonus 2: RSA-like Encryption Demo
 * Simple public key cryptography demo
 */
class SimpleRSA {
  // TODO: Implement simplified RSA
  // constructor(p, q): Two prime numbers
  // encrypt(message): BigInt
  // decrypt(cipher): BigInt
}

/**
 * Bonus 3: Arbitrary Base Conversion
 * Convert BigInt between different bases
 */
function convertBase(value, fromBase, toBase) {
  // TODO: Convert string representation between bases
  // Support bases 2-36
}

// Test:
// console.log(convertBase('FF', 16, 10));  // "255"
// console.log(convertBase('255', 10, 2));  // "11111111"

// ============================================
// SOLUTION KEY (for reference)
// ============================================

/*
// Exercise 1 Solution:
function createBigInts() {
    return {
        literal: 9007199254740993n,
        fromNumber: BigInt(1000),
        fromString: BigInt("123456789012345678901234567890"),
        fromHex: BigInt("0xFFFFFFFFFFFFFFFF"),
        negative: -9007199254740993n
    };
}

// Exercise 2 Solution:
function safeLargeMultiply(a, b) {
    return (BigInt(a) * BigInt(b)).toString();
}

// Exercise 3 Solution:
function bigFactorial(n) {
    let result = 1n;
    for (let i = 2n; i <= BigInt(n); i++) {
        result *= i;
    }
    return result;
}

// Exercise 4 Solution:
function powerOfTwo(exponent) {
    const value = 2n ** BigInt(exponent);
    return { value, digits: value.toString().length };
}

// Exercise 5 Solution:
const bigIntUtils = {
    fromNumber(n) {
        if (!Number.isSafeInteger(n)) {
            throw new Error('Number is not a safe integer');
        }
        return BigInt(n);
    },
    
    toNumber(big) {
        const num = Number(big);
        if (BigInt(num) !== big) {
            throw new Error('Precision would be lost');
        }
        return num;
    },
    
    toString(big, radix = 10) {
        return big.toString(radix);
    },
    
    fromJSON(str) {
        return BigInt(str);
    },
    
    toJSON(big) {
        return big.toString();
    }
};

// Exercise 7 Solution:
function countBits(n) {
    let count = 0n;
    while (n > 0n) {
        count += n & 1n;
        n >>= 1n;
    }
    return count;
}

// Exercise 10 Solution (partial):
const bigMath = {
    sqrt(n) {
        if (n < 0n) throw new Error('Cannot sqrt negative');
        if (n < 2n) return n;
        let x = n;
        let y = (x + 1n) / 2n;
        while (y < x) {
            x = y;
            y = (x + n / x) / 2n;
        }
        return x;
    },
    
    gcd(a, b) {
        a = a < 0n ? -a : a;
        b = b < 0n ? -b : b;
        while (b) {
            [a, b] = [b, a % b];
        }
        return a;
    },
    
    lcm(a, b) {
        return (a * b) / this.gcd(a, b);
    },
    
    modPow(base, exp, mod) {
        let result = 1n;
        base = base % mod;
        while (exp > 0n) {
            if (exp % 2n === 1n) {
                result = (result * base) % mod;
            }
            exp = exp / 2n;
            base = (base * base) % mod;
        }
        return result;
    },
    
    fibonacci(n) {
        if (n <= 1) return BigInt(n);
        let a = 0n, b = 1n;
        for (let i = 2; i <= n; i++) {
            [a, b] = [b, a + b];
        }
        return b;
    }
};
*/

console.log('Complete the exercises above!');
console.log('Check the solution key at the bottom for guidance.');
Exercises - JavaScript Tutorial | DeepML