cpp

exercises

exercises.cpp⚙️
/**
 * C++ Operators - Exercises
 * 
 * Practice problems to reinforce understanding of C++ operators.
 * Each exercise includes a description, TODO section, and hints.
 * Complete solutions are provided in the ANSWER KEY at the bottom.
 * 
 * Difficulty Levels:
 * ⭐ - Beginner
 * ⭐⭐ - Intermediate
 * ⭐⭐⭐ - Advanced
 * 
 * Compile: g++ -std=c++17 -Wall -Wextra exercises.cpp -o exercises
 * Run: ./exercises
 */

#include <iostream>
#include <cmath>
#include <string>
#include <bitset>

using namespace std;

// ============================================================
// Exercise 1: Basic Calculator ⭐
// ============================================================
/**
 * Create a function that takes two numbers and an operator character
 * (+, -, *, /, %) and returns the result of the operation.
 * Handle division by zero by returning 0.
 * 
 * Examples:
 *   calculate(10, 5, '+') returns 15
 *   calculate(10, 5, '-') returns 5
 *   calculate(10, 3, '/') returns 3
 *   calculate(10, 0, '/') returns 0 (division by zero)
 */
double calculate(double a, double b, char op) {
    // TODO: Implement the calculator function
    // Hint: Use if-else or switch statement
    // Hint: Check for division by zero before dividing
    
    return 0; // Replace with your implementation
}

// ============================================================
// Exercise 2: Check Number Properties ⭐
// ============================================================
/**
 * Create a function that checks if a number is:
 * - Positive, negative, or zero
 * - Even or odd (for non-zero integers)
 * 
 * Return a string describing all properties.
 * 
 * Examples:
 *   checkNumber(5) returns "positive odd"
 *   checkNumber(-4) returns "negative even"
 *   checkNumber(0) returns "zero"
 */
string checkNumber(int n) {
    // TODO: Implement the function
    // Hint: Use relational operators (>, <, ==)
    // Hint: Use modulus operator (%) to check even/odd
    
    return ""; // Replace with your implementation
}

// ============================================================
// Exercise 3: Range Checker ⭐
// ============================================================
/**
 * Create a function that checks if a number is within a given range
 * (inclusive on both ends).
 * 
 * Examples:
 *   inRange(5, 1, 10) returns true  (5 is between 1 and 10)
 *   inRange(0, 1, 10) returns false (0 is not between 1 and 10)
 *   inRange(10, 1, 10) returns true (10 is on the boundary)
 */
bool inRange(int value, int min, int max) {
    // TODO: Implement the function
    // Hint: Use logical AND (&&) with relational operators
    
    return false; // Replace with your implementation
}

// ============================================================
// Exercise 4: Leap Year Checker ⭐⭐
// ============================================================
/**
 * Create a function that checks if a year is a leap year.
 * 
 * Rules:
 * - Divisible by 4 AND not divisible by 100, OR
 * - Divisible by 400
 * 
 * Examples:
 *   isLeapYear(2024) returns true
 *   isLeapYear(2023) returns false
 *   isLeapYear(2000) returns true  (divisible by 400)
 *   isLeapYear(1900) returns false (divisible by 100 but not 400)
 */
bool isLeapYear(int year) {
    // TODO: Implement the function
    // Hint: Use modulus (%) and logical operators (&&, ||)
    
    return false; // Replace with your implementation
}

// ============================================================
// Exercise 5: Grade Calculator with Ternary ⭐⭐
// ============================================================
/**
 * Create a function that returns a letter grade based on a score
 * using ONLY the ternary operator (no if-else statements).
 * 
 * 90-100: A
 * 80-89:  B
 * 70-79:  C
 * 60-69:  D
 * Below 60: F
 * 
 * Examples:
 *   getGrade(95) returns 'A'
 *   getGrade(82) returns 'B'
 *   getGrade(55) returns 'F'
 */
char getGrade(int score) {
    // TODO: Implement using ONLY ternary operators (nested ? :)
    // Hint: condition1 ? 'A' : condition2 ? 'B' : ...
    
    return 'F'; // Replace with your implementation
}

// ============================================================
// Exercise 6: Bit Counter ⭐⭐
// ============================================================
/**
 * Create a function that counts the number of 1 bits (set bits)
 * in an unsigned integer.
 * 
 * Examples:
 *   countBits(5) returns 2   (5 = 101 in binary)
 *   countBits(7) returns 3   (7 = 111 in binary)
 *   countBits(0) returns 0
 *   countBits(255) returns 8 (255 = 11111111 in binary)
 */
int countBits(unsigned int n) {
    // TODO: Implement the function
    // Hint: Use a loop with bitwise AND (&) and right shift (>>)
    // Hint: n & 1 gives the last bit
    
    return 0; // Replace with your implementation
}

// ============================================================
// Exercise 7: Power of Two Checker ⭐⭐
// ============================================================
/**
 * Create a function that checks if a positive integer is a power of 2.
 * Use ONLY bitwise operators (no loops, no division).
 * 
 * Powers of 2: 1, 2, 4, 8, 16, 32, ...
 * 
 * Examples:
 *   isPowerOfTwo(1) returns true   (2^0)
 *   isPowerOfTwo(16) returns true  (2^4)
 *   isPowerOfTwo(18) returns false
 *   isPowerOfTwo(0) returns false
 * 
 * Hint: Think about the binary representation of powers of 2.
 * 1 = 0001, 2 = 0010, 4 = 0100, 8 = 1000
 * What happens when you do n & (n-1)?
 */
bool isPowerOfTwo(unsigned int n) {
    // TODO: Implement using bitwise operators only
    // Hint: For power of 2, only one bit is set
    // Hint: n & (n-1) removes the lowest set bit
    
    return false; // Replace with your implementation
}

// ============================================================
// Exercise 8: Swap Using XOR ⭐⭐
// ============================================================
/**
 * Create a function that swaps two integers WITHOUT using a temporary
 * variable. Use XOR bitwise operator.
 * 
 * After calling swap(a, b):
 *   Original values should be exchanged.
 */
void swapXOR(int& a, int& b) {
    // TODO: Swap a and b using only XOR (^) operator
    // Hint: XOR has a special property: x ^ x = 0 and x ^ 0 = x
    // Hint: Three XOR operations are needed
    
    // Your code here
}

// ============================================================
// Exercise 9: Bit Manipulation ⭐⭐⭐
// ============================================================
/**
 * Create functions to:
 * a) Set the nth bit (make it 1)
 * b) Clear the nth bit (make it 0)
 * c) Toggle the nth bit (flip it)
 * d) Check if the nth bit is set
 * 
 * Note: Bits are 0-indexed from the right.
 * 
 * Examples:
 *   setBit(5, 1) returns 7     (101 -> 111)
 *   clearBit(7, 1) returns 5   (111 -> 101)
 *   toggleBit(5, 0) returns 4  (101 -> 100)
 *   isBitSet(5, 2) returns true (bit 2 of 101 is 1)
 */
unsigned int setBit(unsigned int n, int pos) {
    // TODO: Set bit at position pos
    // Hint: Use OR with a mask
    return n; // Replace with your implementation
}

unsigned int clearBit(unsigned int n, int pos) {
    // TODO: Clear bit at position pos
    // Hint: Use AND with inverted mask
    return n; // Replace with your implementation
}

unsigned int toggleBit(unsigned int n, int pos) {
    // TODO: Toggle bit at position pos
    // Hint: Use XOR with a mask
    return n; // Replace with your implementation
}

bool isBitSet(unsigned int n, int pos) {
    // TODO: Check if bit at position pos is set
    // Hint: Use AND with a mask, then check if non-zero
    return false; // Replace with your implementation
}

// ============================================================
// Exercise 10: Approximate Float Comparison ⭐⭐⭐
// ============================================================
/**
 * Create a function that compares two floating-point numbers
 * for approximate equality using both absolute and relative epsilon.
 * 
 * Two numbers are approximately equal if:
 * - Their absolute difference is less than absolute epsilon, OR
 * - Their relative difference is less than relative epsilon
 * 
 * Use abs_epsilon = 1e-12 and rel_epsilon = 1e-9
 * 
 * Examples:
 *   approxEqual(0.1 + 0.2, 0.3) returns true
 *   approxEqual(1000000.0, 1000000.1) may return true (relative)
 *   approxEqual(1.0, 2.0) returns false
 */
bool approxEqual(double a, double b) {
    // TODO: Implement approximate equality comparison
    // Hint: Use fabs() for absolute value
    // Hint: For relative epsilon, divide by max(|a|, |b|)
    
    const double ABS_EPSILON = 1e-12;
    const double REL_EPSILON = 1e-9;
    
    return false; // Replace with your implementation
}

// ============================================================
// BONUS Exercise: Expression Evaluator ⭐⭐⭐
// ============================================================
/**
 * Create a function that evaluates a simple expression with proper
 * operator precedence. The expression contains only single-digit
 * numbers and +, -, *, / operators.
 * 
 * This is a challenging exercise that requires understanding of
 * operator precedence and parsing.
 * 
 * Examples:
 *   evaluate("2+3*4") returns 14 (not 20)
 *   evaluate("8/2+3") returns 7
 *   evaluate("1+2+3") returns 6
 */
double evaluate(const string& expr) {
    // TODO: Implement expression evaluation with precedence
    // This is optional and challenging!
    // Hint: Handle *, / first, then +, -
    
    return 0; // Replace with your implementation
}

// ============================================================
// Test Functions
// ============================================================
void testExercise1() {
    cout << "\n=== Testing Exercise 1: Basic Calculator ===" << endl;
    cout << "calculate(10, 5, '+') = " << calculate(10, 5, '+') << " (expected: 15)" << endl;
    cout << "calculate(10, 5, '-') = " << calculate(10, 5, '-') << " (expected: 5)" << endl;
    cout << "calculate(10, 5, '*') = " << calculate(10, 5, '*') << " (expected: 50)" << endl;
    cout << "calculate(10, 3, '/') = " << calculate(10, 3, '/') << " (expected: 3.33...)" << endl;
    cout << "calculate(10, 3, '%') = " << calculate(10, 3, '%') << " (expected: 1)" << endl;
    cout << "calculate(10, 0, '/') = " << calculate(10, 0, '/') << " (expected: 0)" << endl;
}

void testExercise2() {
    cout << "\n=== Testing Exercise 2: Check Number Properties ===" << endl;
    cout << "checkNumber(5) = \"" << checkNumber(5) << "\" (expected: \"positive odd\")" << endl;
    cout << "checkNumber(-4) = \"" << checkNumber(-4) << "\" (expected: \"negative even\")" << endl;
    cout << "checkNumber(0) = \"" << checkNumber(0) << "\" (expected: \"zero\")" << endl;
    cout << "checkNumber(8) = \"" << checkNumber(8) << "\" (expected: \"positive even\")" << endl;
}

void testExercise3() {
    cout << "\n=== Testing Exercise 3: Range Checker ===" << endl;
    cout << boolalpha;
    cout << "inRange(5, 1, 10) = " << inRange(5, 1, 10) << " (expected: true)" << endl;
    cout << "inRange(0, 1, 10) = " << inRange(0, 1, 10) << " (expected: false)" << endl;
    cout << "inRange(10, 1, 10) = " << inRange(10, 1, 10) << " (expected: true)" << endl;
    cout << "inRange(15, 1, 10) = " << inRange(15, 1, 10) << " (expected: false)" << endl;
}

void testExercise4() {
    cout << "\n=== Testing Exercise 4: Leap Year Checker ===" << endl;
    cout << boolalpha;
    cout << "isLeapYear(2024) = " << isLeapYear(2024) << " (expected: true)" << endl;
    cout << "isLeapYear(2023) = " << isLeapYear(2023) << " (expected: false)" << endl;
    cout << "isLeapYear(2000) = " << isLeapYear(2000) << " (expected: true)" << endl;
    cout << "isLeapYear(1900) = " << isLeapYear(1900) << " (expected: false)" << endl;
}

void testExercise5() {
    cout << "\n=== Testing Exercise 5: Grade Calculator ===" << endl;
    cout << "getGrade(95) = '" << getGrade(95) << "' (expected: 'A')" << endl;
    cout << "getGrade(82) = '" << getGrade(82) << "' (expected: 'B')" << endl;
    cout << "getGrade(75) = '" << getGrade(75) << "' (expected: 'C')" << endl;
    cout << "getGrade(65) = '" << getGrade(65) << "' (expected: 'D')" << endl;
    cout << "getGrade(55) = '" << getGrade(55) << "' (expected: 'F')" << endl;
}

void testExercise6() {
    cout << "\n=== Testing Exercise 6: Bit Counter ===" << endl;
    cout << "countBits(5) = " << countBits(5) << " (expected: 2, binary: 101)" << endl;
    cout << "countBits(7) = " << countBits(7) << " (expected: 3, binary: 111)" << endl;
    cout << "countBits(0) = " << countBits(0) << " (expected: 0)" << endl;
    cout << "countBits(255) = " << countBits(255) << " (expected: 8, binary: 11111111)" << endl;
}

void testExercise7() {
    cout << "\n=== Testing Exercise 7: Power of Two ===" << endl;
    cout << boolalpha;
    cout << "isPowerOfTwo(1) = " << isPowerOfTwo(1) << " (expected: true)" << endl;
    cout << "isPowerOfTwo(16) = " << isPowerOfTwo(16) << " (expected: true)" << endl;
    cout << "isPowerOfTwo(18) = " << isPowerOfTwo(18) << " (expected: false)" << endl;
    cout << "isPowerOfTwo(0) = " << isPowerOfTwo(0) << " (expected: false)" << endl;
}

void testExercise8() {
    cout << "\n=== Testing Exercise 8: XOR Swap ===" << endl;
    int a = 5, b = 10;
    cout << "Before swap: a = " << a << ", b = " << b << endl;
    swapXOR(a, b);
    cout << "After swap:  a = " << a << ", b = " << b << " (expected: a=10, b=5)" << endl;
}

void testExercise9() {
    cout << "\n=== Testing Exercise 9: Bit Manipulation ===" << endl;
    cout << "setBit(5, 1) = " << setBit(5, 1) << " (expected: 7, " << bitset<4>(5) << " -> " << bitset<4>(7) << ")" << endl;
    cout << "clearBit(7, 1) = " << clearBit(7, 1) << " (expected: 5, " << bitset<4>(7) << " -> " << bitset<4>(5) << ")" << endl;
    cout << "toggleBit(5, 0) = " << toggleBit(5, 0) << " (expected: 4, " << bitset<4>(5) << " -> " << bitset<4>(4) << ")" << endl;
    cout << boolalpha;
    cout << "isBitSet(5, 2) = " << isBitSet(5, 2) << " (expected: true)" << endl;
    cout << "isBitSet(5, 1) = " << isBitSet(5, 1) << " (expected: false)" << endl;
}

void testExercise10() {
    cout << "\n=== Testing Exercise 10: Approximate Float Comparison ===" << endl;
    cout << boolalpha;
    cout << "approxEqual(0.1 + 0.2, 0.3) = " << approxEqual(0.1 + 0.2, 0.3) << " (expected: true)" << endl;
    cout << "approxEqual(1.0, 2.0) = " << approxEqual(1.0, 2.0) << " (expected: false)" << endl;
    cout << "approxEqual(1000000.0, 1000000.0000001) = " << approxEqual(1000000.0, 1000000.0000001) << " (expected: true)" << endl;
}

void testBonus() {
    cout << "\n=== Testing BONUS: Expression Evaluator ===" << endl;
    cout << "evaluate(\"2+3*4\") = " << evaluate("2+3*4") << " (expected: 14)" << endl;
    cout << "evaluate(\"8/2+3\") = " << evaluate("8/2+3") << " (expected: 7)" << endl;
    cout << "evaluate(\"1+2+3\") = " << evaluate("1+2+3") << " (expected: 6)" << endl;
}

// ============================================================
// Main Function
// ============================================================
int main() {
    cout << "╔════════════════════════════════════════════════════════════╗" << endl;
    cout << "║              C++ OPERATORS - EXERCISES                     ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════╝" << endl;
    
    testExercise1();
    testExercise2();
    testExercise3();
    testExercise4();
    testExercise5();
    testExercise6();
    testExercise7();
    testExercise8();
    testExercise9();
    testExercise10();
    testBonus();
    
    cout << "\n╔════════════════════════════════════════════════════════════╗" << endl;
    cout << "║         Complete the TODO sections and re-run!             ║" << endl;
    cout << "╚════════════════════════════════════════════════════════════╝" << endl;
    
    return 0;
}

// ============================================================
// ANSWER KEY
// ============================================================
/*
 * Below are the complete solutions for all exercises.
 * Try to solve them yourself first before looking!
 */

/*
// Exercise 1: Basic Calculator
double calculate(double a, double b, char op) {
    switch (op) {
        case '+': return a + b;
        case '-': return a - b;
        case '*': return a * b;
        case '/': return (b != 0) ? a / b : 0;
        case '%': return (b != 0) ? static_cast<int>(a) % static_cast<int>(b) : 0;
        default: return 0;
    }
}

// Exercise 2: Check Number Properties
string checkNumber(int n) {
    if (n == 0) return "zero";
    
    string result = (n > 0) ? "positive " : "negative ";
    result += (n % 2 == 0) ? "even" : "odd";
    return result;
}

// Exercise 3: Range Checker
bool inRange(int value, int min, int max) {
    return value >= min && value <= max;
}

// Exercise 4: Leap Year Checker
bool isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// Exercise 5: Grade Calculator
char getGrade(int score) {
    return (score >= 90) ? 'A' :
           (score >= 80) ? 'B' :
           (score >= 70) ? 'C' :
           (score >= 60) ? 'D' : 'F';
}

// Exercise 6: Bit Counter
int countBits(unsigned int n) {
    int count = 0;
    while (n) {
        count += n & 1;
        n >>= 1;
    }
    return count;
}

// Exercise 7: Power of Two
bool isPowerOfTwo(unsigned int n) {
    return n > 0 && (n & (n - 1)) == 0;
}

// Exercise 8: XOR Swap
void swapXOR(int& a, int& b) {
    if (&a != &b) {  // Avoid self-swap issues
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
    }
}

// Exercise 9: Bit Manipulation
unsigned int setBit(unsigned int n, int pos) {
    return n | (1 << pos);
}

unsigned int clearBit(unsigned int n, int pos) {
    return n & ~(1 << pos);
}

unsigned int toggleBit(unsigned int n, int pos) {
    return n ^ (1 << pos);
}

bool isBitSet(unsigned int n, int pos) {
    return (n & (1 << pos)) != 0;
}

// Exercise 10: Approximate Float Comparison
bool approxEqual(double a, double b) {
    const double ABS_EPSILON = 1e-12;
    const double REL_EPSILON = 1e-9;
    
    double diff = fabs(a - b);
    
    // Check absolute difference
    if (diff < ABS_EPSILON) return true;
    
    // Check relative difference
    double larger = max(fabs(a), fabs(b));
    if (larger > 0 && diff / larger < REL_EPSILON) return true;
    
    return false;
}

// BONUS: Expression Evaluator (simplified version)
double evaluate(const string& expr) {
    vector<double> nums;
    vector<char> ops;
    
    // Parse the expression
    for (size_t i = 0; i < expr.length(); i++) {
        if (isdigit(expr[i])) {
            nums.push_back(expr[i] - '0');
        } else if (expr[i] == '+' || expr[i] == '-' || 
                   expr[i] == '*' || expr[i] == '/') {
            ops.push_back(expr[i]);
        }
    }
    
    // First pass: handle * and /
    for (size_t i = 0; i < ops.size(); ) {
        if (ops[i] == '*' || ops[i] == '/') {
            double result = (ops[i] == '*') ? 
                nums[i] * nums[i+1] : nums[i] / nums[i+1];
            nums[i] = result;
            nums.erase(nums.begin() + i + 1);
            ops.erase(ops.begin() + i);
        } else {
            i++;
        }
    }
    
    // Second pass: handle + and -
    double result = nums[0];
    for (size_t i = 0; i < ops.size(); i++) {
        if (ops[i] == '+') result += nums[i+1];
        else if (ops[i] == '-') result -= nums[i+1];
    }
    
    return result;
}
*/
Exercises - C++ Tutorial | DeepML