javascript

exercises

exercises.js⚑
/**
 * ============================================
 * 3.2 Comparison Operators - Exercises
 * ============================================
 *
 * Practice comparison operations in JavaScript.
 * Solutions are at the bottom.
 */

// ============================================
// EXERCISE 1: Predict Loose Equality
// ============================================
// Without running, predict true or false:

// 5 == "5"            β†’ _____
// 0 == false          β†’ _____
// 0 == ""             β†’ _____
// null == undefined   β†’ _____
// false == "false"    β†’ _____
// true == 1           β†’ _____
// true == "1"         β†’ _____
// [] == false         β†’ _____
// [1] == true         β†’ _____
// "" == false         β†’ _____

// ============================================
// EXERCISE 2: Predict Strict Equality
// ============================================
// Without running, predict true or false:

// 5 === "5"           β†’ _____
// 0 === false         β†’ _____
// null === undefined  β†’ _____
// NaN === NaN         β†’ _____
// Infinity === Infinity β†’ _____
// -0 === +0           β†’ _____
// [] === []           β†’ _____
// {} === {}           β†’ _____

// ============================================
// EXERCISE 3: Relational Operators
// ============================================
// Predict the results:

// 5 > 3               β†’ _____
// "apple" < "banana"  β†’ _____
// "10" < "9"          β†’ _____
// 10 < 9              β†’ _____
// "10" > 9            β†’ _____
// null >= 0           β†’ _____
// null == 0           β†’ _____
// undefined > 0       β†’ _____

// ============================================
// EXERCISE 4: Fix the Bug
// ============================================
// This function has a bug. Find and fix it:

function isPositive(value) {
  if (value == 0) {
    return false;
  }
  return value > 0;
}

// Bug: isPositive("0") returns true when it should return false
// YOUR FIX:

// ============================================
// EXERCISE 5: Validate User Age
// ============================================
// Create a function that validates age input:
// - Returns true if age is a valid number between 0 and 120
// - Handle string inputs (convert to number first)
// - Return false for NaN, negative, or invalid inputs

function isValidAge(age) {
  // YOUR CODE:
}

// Tests:
// isValidAge(25)       β†’ true
// isValidAge("30")     β†’ true
// isValidAge(-5)       β†’ false
// isValidAge(150)      β†’ false
// isValidAge("abc")    β†’ false
// isValidAge(NaN)      β†’ false
// isValidAge(null)     β†’ false

// ============================================
// EXERCISE 6: Compare Arrays
// ============================================
// Create a function to compare two arrays for equality

function arraysEqual(arr1, arr2) {
  // Return true if both arrays have the same elements in same order
  // YOUR CODE:
}

// Tests:
// arraysEqual([1, 2, 3], [1, 2, 3])     β†’ true
// arraysEqual([1, 2, 3], [1, 2])        β†’ false
// arraysEqual([1, 2, 3], [1, 3, 2])     β†’ false
// arraysEqual([], [])                   β†’ true
// arraysEqual([1], [1])                 β†’ true

// ============================================
// EXERCISE 7: Case-Insensitive Compare
// ============================================
// Create a function for case-insensitive string comparison

function equalsIgnoreCase(str1, str2) {
  // Return true if strings are equal ignoring case
  // Handle null/undefined inputs
  // YOUR CODE:
}

// Tests:
// equalsIgnoreCase("Hello", "hello")    β†’ true
// equalsIgnoreCase("WORLD", "world")    β†’ true
// equalsIgnoreCase("Test", "Testy")     β†’ false
// equalsIgnoreCase(null, "test")        β†’ false

// ============================================
// EXERCISE 8: Object Deep Equal
// ============================================
// Create a function to deeply compare two objects

function deepEqual(obj1, obj2) {
  // Compare objects recursively
  // Handle nested objects and arrays
  // YOUR CODE:
}

// Tests:
// deepEqual({a: 1}, {a: 1})             β†’ true
// deepEqual({a: 1}, {a: 2})             β†’ false
// deepEqual({a: {b: 1}}, {a: {b: 1}})   β†’ true
// deepEqual([1, [2, 3]], [1, [2, 3]])   β†’ true
// deepEqual(null, null)                 β†’ true
// deepEqual(5, 5)                       β†’ true

// ============================================
// EXERCISE 9: In Range Check
// ============================================
// Create a function to check if value is in range

function inRange(value, min, max, inclusive = true) {
  // Return true if value is between min and max
  // If inclusive is true: min <= value <= max
  // If inclusive is false: min < value < max
  // YOUR CODE:
}

// Tests:
// inRange(5, 1, 10)              β†’ true
// inRange(1, 1, 10)              β†’ true (inclusive)
// inRange(1, 1, 10, false)       β†’ false (exclusive)
// inRange(10, 1, 10, false)      β†’ false (exclusive)
// inRange(0, 1, 10)              β†’ false

// ============================================
// EXERCISE 10: Find Comparison Type
// ============================================
// Create a function that returns how two values compare

function compare(a, b) {
  // Return:
  // -1 if a < b
  // 0 if a === b
  // 1 if a > b
  // NaN if comparison is not meaningful (e.g., involving NaN)
  // YOUR CODE:
}

// Tests:
// compare(5, 10)          β†’ -1
// compare(10, 5)          β†’ 1
// compare(5, 5)           β†’ 0
// compare("a", "b")       β†’ -1
// compare(NaN, 5)         β†’ NaN

// ============================================
// EXERCISE 11: Safe Equality Check
// ============================================
// Create a function for safe equality that handles edge cases

function safeEquals(a, b) {
  // Handle special cases:
  // - NaN should equal NaN
  // - +0 should NOT equal -0
  // - Otherwise use strict equality
  // YOUR CODE:
}

// Tests:
// safeEquals(5, 5)        β†’ true
// safeEquals(NaN, NaN)    β†’ true
// safeEquals(0, -0)       β†’ false
// safeEquals("a", "a")    β†’ true
// safeEquals(null, undefined) β†’ false

// ============================================
// EXERCISE 12: Transitivity Test
// ============================================
// Demonstrate the transitivity problem with ==
// Find values where a == b and b == c but a != c

// YOUR VALUES:
// a = _____
// b = _____
// c = _____

// Verify:
// a == b β†’ _____
// b == c β†’ _____
// a == c β†’ _____ (should be false!)

// ============================================
// EXERCISE 13: Sort with Comparison
// ============================================
// Create a comparison function for sorting people by age

const people = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 },
  { name: 'Diana', age: 25 },
];

function sortByAge(people) {
  // Sort by age ascending
  // If same age, sort by name alphabetically
  // YOUR CODE:
}

// Expected: Bob, Diana, Alice, Charlie

// ============================================
// EXERCISE 14: String Version Compare
// ============================================
// Create a function to compare version strings

function compareVersions(v1, v2) {
  // Compare version strings like "1.2.3" and "1.2.4"
  // Return -1 if v1 < v2, 0 if equal, 1 if v1 > v2
  // YOUR CODE:
}

// Tests:
// compareVersions("1.0.0", "1.0.1")     β†’ -1
// compareVersions("1.2.0", "1.1.9")     β†’ 1
// compareVersions("2.0.0", "1.9.9")     β†’ 1
// compareVersions("1.0.0", "1.0.0")     β†’ 0
// compareVersions("1.0", "1.0.0")       β†’ 0

// ============================================
// EXERCISE 15: Between Dates Check
// ============================================
// Create a function to check if a date is between two others

function isBetweenDates(date, startDate, endDate) {
  // Return true if date is between start and end (inclusive)
  // All parameters are Date objects or valid date strings
  // YOUR CODE:
}

// Tests:
// isBetweenDates(new Date("2024-06-15"), new Date("2024-01-01"), new Date("2024-12-31")) β†’ true
// isBetweenDates(new Date("2023-06-15"), new Date("2024-01-01"), new Date("2024-12-31")) β†’ false

// ============================================
// ============================================
//              SOLUTIONS
// ============================================
// ============================================

/*

// SOLUTION 1: Predict Loose Equality
// 5 == "5"            β†’ true
// 0 == false          β†’ true
// 0 == ""             β†’ true
// null == undefined   β†’ true
// false == "false"    → false (false→0, "false"→NaN)
// true == 1           β†’ true
// true == "1"         β†’ true
// [] == false         β†’ true
// [1] == true         β†’ true
// "" == false         β†’ true


// SOLUTION 2: Predict Strict Equality
// 5 === "5"           β†’ false
// 0 === false         β†’ false
// null === undefined  β†’ false
// NaN === NaN         β†’ false
// Infinity === Infinity β†’ true
// -0 === +0           β†’ true
// [] === []           β†’ false
// {} === {}           β†’ false


// SOLUTION 3: Relational Operators
// 5 > 3               β†’ true
// "apple" < "banana"  β†’ true
// "10" < "9"          β†’ true (string comparison!)
// 10 < 9              β†’ false
// "10" > 9            β†’ true (string converts to number)
// null >= 0           β†’ true
// null == 0           β†’ false
// undefined > 0       β†’ false


// SOLUTION 4: Fix the Bug
function isPositive(value) {
    let num = Number(value);
    if (Number.isNaN(num)) {
        return false;
    }
    return num > 0;
}


// SOLUTION 5: Validate User Age
function isValidAge(age) {
    let num = Number(age);
    if (Number.isNaN(num)) return false;
    return num >= 0 && num <= 120 && Number.isInteger(num);
}


// SOLUTION 6: Compare Arrays
function arraysEqual(arr1, arr2) {
    if (arr1.length !== arr2.length) return false;
    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) return false;
    }
    return true;
}


// SOLUTION 7: Case-Insensitive Compare
function equalsIgnoreCase(str1, str2) {
    if (str1 === null || str1 === undefined) return false;
    if (str2 === null || str2 === undefined) return false;
    return str1.toLowerCase() === str2.toLowerCase();
}


// SOLUTION 8: Object Deep Equal
function deepEqual(obj1, obj2) {
    // Handle primitives and same reference
    if (obj1 === obj2) return true;
    
    // Handle null
    if (obj1 === null || obj2 === null) return false;
    
    // Handle NaN
    if (Number.isNaN(obj1) && Number.isNaN(obj2)) return true;
    
    // Handle different types
    if (typeof obj1 !== typeof obj2) return false;
    if (typeof obj1 !== 'object') return false;
    
    // Handle arrays
    if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;
    
    let keys1 = Object.keys(obj1);
    let keys2 = Object.keys(obj2);
    
    if (keys1.length !== keys2.length) return false;
    
    for (let key of keys1) {
        if (!keys2.includes(key)) return false;
        if (!deepEqual(obj1[key], obj2[key])) return false;
    }
    
    return true;
}


// SOLUTION 9: In Range Check
function inRange(value, min, max, inclusive = true) {
    if (inclusive) {
        return value >= min && value <= max;
    }
    return value > min && value < max;
}


// SOLUTION 10: Find Comparison Type
function compare(a, b) {
    if (Number.isNaN(a) || Number.isNaN(b)) return NaN;
    if (a === b) return 0;
    return a < b ? -1 : 1;
}


// SOLUTION 11: Safe Equality Check
function safeEquals(a, b) {
    return Object.is(a, b);
}
// Or manually:
function safeEquals(a, b) {
    if (Number.isNaN(a) && Number.isNaN(b)) return true;
    if (a === 0 && b === 0) return 1/a === 1/b;
    return a === b;
}


// SOLUTION 12: Transitivity Test
// a = "0"
// b = 0
// c = ""
// "0" == 0  β†’ true
// 0 == ""   β†’ true
// "0" == "" β†’ false!


// SOLUTION 13: Sort with Comparison
function sortByAge(people) {
    return [...people].sort((a, b) => {
        if (a.age !== b.age) {
            return a.age - b.age;
        }
        return a.name.localeCompare(b.name);
    });
}


// SOLUTION 14: String Version Compare
function compareVersions(v1, v2) {
    let parts1 = v1.split('.').map(Number);
    let parts2 = v2.split('.').map(Number);
    
    let maxLength = Math.max(parts1.length, parts2.length);
    
    for (let i = 0; i < maxLength; i++) {
        let p1 = parts1[i] || 0;
        let p2 = parts2[i] || 0;
        
        if (p1 < p2) return -1;
        if (p1 > p2) return 1;
    }
    
    return 0;
}


// SOLUTION 15: Between Dates Check
function isBetweenDates(date, startDate, endDate) {
    let d = new Date(date).getTime();
    let start = new Date(startDate).getTime();
    let end = new Date(endDate).getTime();
    
    return d >= start && d <= end;
}

*/
Exercises - JavaScript Tutorial | DeepML