cpp

exercises

exercises.cpp⚙️
/**
 * Enums, Structs, and Unions - Exercises
 * Practice problems from beginner to advanced
 */

#include <iostream>
#include <string>
#include <vector>
#include <variant>
#include <cmath>

using std::cout;
using std::endl;
using std::string;

// ============================================================================
// EXERCISE 1: Enum Class Basics (Beginner)
// ============================================================================
/**
 * TODO: Create an enum class called Month with all 12 months.
 * Each month should have a value from 1-12 (January = 1, December = 12).
 * The underlying type should be uint8_t.
 * 
 * Then create a function:
 *   string monthToString(Month m) - returns the month name as a string
 *   int daysInMonth(Month m, bool isLeapYear = false) - returns days in month
 */

// YOUR CODE HERE:
// enum class Month : uint8_t { ... };
// string monthToString(Month m) { ... }
// int daysInMonth(Month m, bool isLeapYear = false) { ... }

void exercise1_test() {
    cout << "=== EXERCISE 1: Enum Class Basics ===" << endl;
    
    // Uncomment to test:
    /*
    cout << monthToString(Month::January) << " has " 
         << daysInMonth(Month::January) << " days" << endl;
    cout << monthToString(Month::February) << " has " 
         << daysInMonth(Month::February) << " days (non-leap)" << endl;
    cout << monthToString(Month::February) << " has " 
         << daysInMonth(Month::February, true) << " days (leap year)" << endl;
    cout << monthToString(Month::December) << " has " 
         << daysInMonth(Month::December) << " days" << endl;
    */
}

// ============================================================================
// EXERCISE 2: Enum Operations (Beginner)
// ============================================================================
/**
 * TODO: Create an enum class FilePermission with flags:
 *   None = 0, Read = 1, Write = 2, Execute = 4
 * 
 * Implement these operator overloads to allow combining permissions:
 *   operator| (combine permissions)
 *   operator& (check if permission is set)
 *   operator~ (invert permissions - within 3 bits)
 * 
 * Create functions:
 *   bool hasPermission(FilePermission perms, FilePermission check)
 *   string permissionString(FilePermission perms) - returns "rwx" style
 */

// YOUR CODE HERE:

void exercise2_test() {
    cout << "\n=== EXERCISE 2: Enum Operations ===" << endl;
    
    // Uncomment to test:
    /*
    FilePermission perms = FilePermission::Read | FilePermission::Write;
    
    cout << "Permissions: " << permissionString(perms) << endl;
    cout << "Has Read? " << hasPermission(perms, FilePermission::Read) << endl;
    cout << "Has Execute? " << hasPermission(perms, FilePermission::Execute) << endl;
    
    perms = perms | FilePermission::Execute;
    cout << "After adding Execute: " << permissionString(perms) << endl;
    */
}

// ============================================================================
// EXERCISE 3: Basic Struct (Beginner)
// ============================================================================
/**
 * TODO: Create a struct called Vector2D with:
 *   - double x, y (coordinates)
 *   - double length() const - returns the magnitude
 *   - Vector2D normalize() const - returns unit vector
 *   - Vector2D operator+(const Vector2D& other) const
 *   - Vector2D operator-(const Vector2D& other) const
 *   - Vector2D operator*(double scalar) const
 *   - double dot(const Vector2D& other) const - dot product
 *   - void print() const - prints "(x, y)"
 */

// YOUR CODE HERE:

void exercise3_test() {
    cout << "\n=== EXERCISE 3: Basic Struct ===" << endl;
    
    // Uncomment to test:
    /*
    Vector2D v1{3.0, 4.0};
    Vector2D v2{1.0, 2.0};
    
    cout << "v1: "; v1.print();
    cout << "v2: "; v2.print();
    cout << "v1.length() = " << v1.length() << endl;
    
    Vector2D v3 = v1 + v2;
    cout << "v1 + v2 = "; v3.print();
    
    Vector2D v4 = v1 - v2;
    cout << "v1 - v2 = "; v4.print();
    
    Vector2D v5 = v1 * 2.0;
    cout << "v1 * 2 = "; v5.print();
    
    cout << "v1.dot(v2) = " << v1.dot(v2) << endl;
    
    Vector2D unit = v1.normalize();
    cout << "v1.normalize() = "; unit.print();
    cout << "Normalized length = " << unit.length() << endl;
    */
}

// ============================================================================
// EXERCISE 4: Nested Structs (Intermediate)
// ============================================================================
/**
 * TODO: Design a library system with these structs:
 * 
 * Author:
 *   - string firstName, lastName
 *   - int birthYear
 *   - string fullName() const
 * 
 * Book:
 *   - string title
 *   - Author author
 *   - int year
 *   - string isbn
 *   - double price
 *   - void print() const
 * 
 * Library:
 *   - string name
 *   - vector<Book> books
 *   - void addBook(const Book& book)
 *   - Book* findByISBN(const string& isbn)
 *   - vector<Book> findByAuthor(const string& lastName)
 *   - void printCatalog() const
 */

// YOUR CODE HERE:

void exercise4_test() {
    cout << "\n=== EXERCISE 4: Nested Structs ===" << endl;
    
    // Uncomment to test:
    /*
    Library lib{"City Library"};
    
    lib.addBook({
        "The C++ Programming Language",
        {"Bjarne", "Stroustrup", 1950},
        2013,
        "978-0321563842",
        59.99
    });
    
    lib.addBook({
        "Effective Modern C++",
        {"Scott", "Meyers", 1959},
        2014,
        "978-1491903995",
        49.99
    });
    
    lib.printCatalog();
    
    if (Book* book = lib.findByISBN("978-0321563842")) {
        cout << "\nFound by ISBN: ";
        book->print();
    }
    
    auto results = lib.findByAuthor("Meyers");
    cout << "\nBooks by Meyers: " << results.size() << endl;
    */
}

// ============================================================================
// EXERCISE 5: Memory Layout Optimization (Intermediate)
// ============================================================================
/**
 * TODO: Given this poorly-arranged struct, create an optimized version
 * that uses less memory.
 * 
 * Original (unoptimized):
 * struct BadLayout {
 *     bool flag1;      // 1 byte
 *     double value;    // 8 bytes
 *     bool flag2;      // 1 byte
 *     int count;       // 4 bytes
 *     char letter;     // 1 byte
 *     int id;          // 4 bytes
 *     bool flag3;      // 1 byte
 * };
 * 
 * Create:
 * struct OptimizedLayout { ... };
 * 
 * The optimized version should have the same members but arranged
 * to minimize padding.
 */

struct BadLayout {
    bool flag1;
    double value;
    bool flag2;
    int count;
    char letter;
    int id;
    bool flag3;
};

// YOUR CODE HERE:
// struct OptimizedLayout { ... };

void exercise5_test() {
    cout << "\n=== EXERCISE 5: Memory Layout Optimization ===" << endl;
    
    cout << "BadLayout size: " << sizeof(BadLayout) << " bytes" << endl;
    
    // Uncomment to test:
    /*
    cout << "OptimizedLayout size: " << sizeof(OptimizedLayout) << " bytes" << endl;
    cout << "Saved: " << (sizeof(BadLayout) - sizeof(OptimizedLayout)) << " bytes" << endl;
    */
}

// ============================================================================
// EXERCISE 6: Tagged Union (Intermediate)
// ============================================================================
/**
 * TODO: Create a JSON-like value type using a tagged union:
 * 
 * enum class JsonType { Null, Bool, Number, String, Array, Object };
 * 
 * struct JsonValue {
 *     JsonType type;
 *     union { ... };
 *     
 *     // Factory methods
 *     static JsonValue null();
 *     static JsonValue boolean(bool b);
 *     static JsonValue number(double n);
 *     static JsonValue string(const char* s);
 *     
 *     // Type checks
 *     bool isNull() const;
 *     bool isBool() const;
 *     bool isNumber() const;
 *     bool isString() const;
 *     
 *     // Getters (should check type first)
 *     bool asBool() const;
 *     double asNumber() const;
 *     const char* asString() const;
 *     
 *     void print() const;
 * };
 * 
 * For simplicity, use a fixed char array for strings.
 */

// YOUR CODE HERE:

void exercise6_test() {
    cout << "\n=== EXERCISE 6: Tagged Union ===" << endl;
    
    // Uncomment to test:
    /*
    JsonValue values[] = {
        JsonValue::null(),
        JsonValue::boolean(true),
        JsonValue::number(42.5),
        JsonValue::string("hello")
    };
    
    for (const auto& v : values) {
        v.print();
    }
    */
}

// ============================================================================
// EXERCISE 7: std::variant Calculator (Intermediate)
// ============================================================================
/**
 * TODO: Create a calculator that can handle different number types.
 * 
 * using Number = std::variant<int, double, std::complex<double>>;
 * 
 * Create functions:
 *   Number add(const Number& a, const Number& b)
 *   Number subtract(const Number& a, const Number& b)
 *   Number multiply(const Number& a, const Number& b)
 *   Number divide(const Number& a, const Number& b)
 *   void printNumber(const Number& n)
 * 
 * The operations should work with any combination of types.
 * When mixing types, promote to the more complex type.
 */

// YOUR CODE HERE:

void exercise7_test() {
    cout << "\n=== EXERCISE 7: std::variant Calculator ===" << endl;
    
    // Uncomment to test:
    /*
    Number a = 10;
    Number b = 3.5;
    
    cout << "a = "; printNumber(a);
    cout << "b = "; printNumber(b);
    cout << "a + b = "; printNumber(add(a, b));
    cout << "a * b = "; printNumber(multiply(a, b));
    cout << "a / b = "; printNumber(divide(a, b));
    */
}

// ============================================================================
// EXERCISE 8: Bit Fields for Protocol Header (Advanced)
// ============================================================================
/**
 * TODO: Implement a simplified TCP header using bit fields:
 * 
 * struct TCPHeader {
 *     uint16_t sourcePort;      // 16 bits
 *     uint16_t destPort;        // 16 bits
 *     uint32_t sequenceNum;     // 32 bits
 *     uint32_t ackNum;          // 32 bits
 *     
 *     // These should be bit fields packed into 16 bits:
 *     uint16_t dataOffset : 4;  // 4 bits
 *     uint16_t reserved : 3;    // 3 bits
 *     uint16_t ns : 1;          // 1 bit (ECN-nonce)
 *     uint16_t cwr : 1;         // 1 bit
 *     uint16_t ece : 1;         // 1 bit
 *     uint16_t urg : 1;         // 1 bit
 *     uint16_t ack : 1;         // 1 bit
 *     uint16_t psh : 1;         // 1 bit
 *     uint16_t rst : 1;         // 1 bit
 *     uint16_t syn : 1;         // 1 bit
 *     uint16_t fin : 1;         // 1 bit
 *     
 *     uint16_t windowSize;      // 16 bits
 *     uint16_t checksum;        // 16 bits
 *     uint16_t urgentPointer;   // 16 bits
 *     
 *     void print() const;
 *     void setFlag(const string& flagName, bool value);
 *     bool getFlag(const string& flagName) const;
 * };
 * 
 * Total size should be 20 bytes (160 bits).
 */

// YOUR CODE HERE:

void exercise8_test() {
    cout << "\n=== EXERCISE 8: Bit Fields for Protocol Header ===" << endl;
    
    // Uncomment to test:
    /*
    TCPHeader header = {};
    header.sourcePort = 443;
    header.destPort = 12345;
    header.sequenceNum = 1000;
    header.ackNum = 5000;
    header.dataOffset = 5;
    header.syn = 1;
    header.ack = 1;
    header.windowSize = 65535;
    
    cout << "sizeof(TCPHeader) = " << sizeof(TCPHeader) << " bytes" << endl;
    header.print();
    
    cout << "\nSYN flag: " << header.getFlag("syn") << endl;
    cout << "FIN flag: " << header.getFlag("fin") << endl;
    */
}

// ============================================================================
// EXERCISE 9: Shape Hierarchy with std::variant (Advanced)
// ============================================================================
/**
 * TODO: Create a type-safe shape system without virtual functions.
 * 
 * Structs for each shape:
 *   Circle { double radius; }
 *   Rectangle { double width, height; }
 *   Triangle { double a, b, c; }  // sides
 * 
 * using Shape = std::variant<Circle, Rectangle, Triangle>;
 * 
 * Create visitor functions using std::visit:
 *   double area(const Shape& s)
 *   double perimeter(const Shape& s)
 *   string name(const Shape& s)
 *   void print(const Shape& s)
 * 
 * Create a function to calculate total area of a vector of shapes.
 */

// YOUR CODE HERE:

void exercise9_test() {
    cout << "\n=== EXERCISE 9: Shape Hierarchy with std::variant ===" << endl;
    
    // Uncomment to test:
    /*
    std::vector<Shape> shapes = {
        Circle{5.0},
        Rectangle{4.0, 6.0},
        Triangle{3.0, 4.0, 5.0}
    };
    
    for (const auto& shape : shapes) {
        print(shape);
    }
    
    double total = 0;
    for (const auto& shape : shapes) {
        total += area(shape);
    }
    cout << "\nTotal area: " << total << endl;
    */
}

// ============================================================================
// EXERCISE 10: State Machine with Enum and Struct (Advanced)
// ============================================================================
/**
 * TODO: Implement a traffic light state machine:
 * 
 * enum class LightState { Red, Yellow, Green };
 * enum class Event { Timer, Emergency, Reset };
 * 
 * struct TrafficLight {
 *     LightState state;
 *     int redDuration;
 *     int yellowDuration;
 *     int greenDuration;
 *     int elapsedTime;
 *     bool emergencyMode;
 *     
 *     TrafficLight(int red, int yellow, int green);
 *     
 *     void processEvent(Event e);
 *     void tick();  // Advance time by 1 second
 *     bool shouldTransition() const;
 *     LightState nextState() const;
 *     void transition();
 *     
 *     string stateString() const;
 *     void print() const;
 * };
 * 
 * Normal flow: Red -> Green -> Yellow -> Red
 * Emergency sets to Red and stays there until Reset
 */

// YOUR CODE HERE:

void exercise10_test() {
    cout << "\n=== EXERCISE 10: State Machine ===" << endl;
    
    // Uncomment to test:
    /*
    TrafficLight light(30, 5, 25);  // Red: 30s, Yellow: 5s, Green: 25s
    
    cout << "Initial state:" << endl;
    light.print();
    
    // Simulate some time passing
    for (int i = 0; i < 35; i++) {
        light.tick();
    }
    cout << "\nAfter 35 seconds:" << endl;
    light.print();
    
    // Test emergency
    light.processEvent(Event::Emergency);
    cout << "\nAfter emergency:" << endl;
    light.print();
    
    light.processEvent(Event::Reset);
    cout << "\nAfter reset:" << endl;
    light.print();
    */
}

// ============================================================================
// CHALLENGE: Entity Component System (Expert)
// ============================================================================
/**
 * TODO: Implement a simple Entity Component System (ECS):
 * 
 * Components (structs):
 *   Position { float x, y, z; }
 *   Velocity { float dx, dy, dz; }
 *   Health { int current, max; }
 *   Render { string mesh; string texture; }
 *   
 * using Component = std::variant<Position, Velocity, Health, Render>;
 * 
 * struct Entity {
 *     uint32_t id;
 *     std::vector<Component> components;
 *     
 *     template<typename T>
 *     void addComponent(const T& comp);
 *     
 *     template<typename T>
 *     T* getComponent();
 *     
 *     template<typename T>
 *     bool hasComponent() const;
 *     
 *     template<typename T>
 *     void removeComponent();
 * };
 * 
 * struct World {
 *     std::vector<Entity> entities;
 *     uint32_t nextId;
 *     
 *     Entity& createEntity();
 *     void destroyEntity(uint32_t id);
 *     
 *     // Process all entities with Position and Velocity
 *     void movementSystem(float deltaTime);
 *     
 *     // Process all entities with Health
 *     void healthSystem();
 * };
 */

// YOUR CODE HERE:

void exercise_challenge_test() {
    cout << "\n=== CHALLENGE: Entity Component System ===" << endl;
    
    // Uncomment to test:
    /*
    World world;
    
    // Create player entity
    Entity& player = world.createEntity();
    player.addComponent(Position{0, 0, 0});
    player.addComponent(Velocity{1, 0, 0});
    player.addComponent(Health{100, 100});
    player.addComponent(Render{"player.obj", "player.png"});
    
    // Create enemy entity
    Entity& enemy = world.createEntity();
    enemy.addComponent(Position{10, 0, 5});
    enemy.addComponent(Velocity{-1, 0, 0});
    enemy.addComponent(Health{50, 50});
    
    cout << "Initial state:" << endl;
    for (const auto& e : world.entities) {
        if (auto* pos = e.getComponent<Position>()) {
            cout << "Entity " << e.id << " at (" 
                 << pos->x << ", " << pos->y << ", " << pos->z << ")" << endl;
        }
    }
    
    // Simulate
    for (int i = 0; i < 5; i++) {
        world.movementSystem(1.0f);
    }
    
    cout << "\nAfter 5 seconds:" << endl;
    for (const auto& e : world.entities) {
        if (auto* pos = e.getComponent<Position>()) {
            cout << "Entity " << e.id << " at (" 
                 << pos->x << ", " << pos->y << ", " << pos->z << ")" << endl;
        }
    }
    */
}

// ============================================================================
// MAIN
// ============================================================================

int main() {
    cout << "╔══════════════════════════════════════════════════════════════╗" << endl;
    cout << "║       ENUMS, STRUCTS, UNIONS - EXERCISES                     ║" << endl;
    cout << "╚══════════════════════════════════════════════════════════════╝" << endl;
    
    exercise1_test();
    exercise2_test();
    exercise3_test();
    exercise4_test();
    exercise5_test();
    exercise6_test();
    exercise7_test();
    exercise8_test();
    exercise9_test();
    exercise10_test();
    exercise_challenge_test();
    
    cout << "\n═══════════════════════════════════════════════════════════════" << endl;
    cout << "Complete the exercises by implementing the TODO sections!" << endl;
    cout << "Uncomment the test code after implementing each exercise." << endl;
    
    return 0;
}
Exercises - C++ Tutorial | DeepML