[C++] - Rotate & Drop Stones || Extensive Test Cases || Refactored code
To solve the problem of rotating the box and letting the stones fall due to gravity, we can follow these steps:

Initialize the Rotated Box: Create a new matrix
To solve the problem of rotating the box and letting the stones fall due to gravity, we can follow these steps:

- **Initialize the Rotated Box:** Create a new matrix to represent the rotated box. This matrix will have dimensions n x m (the transpose of the original m x n matrix), initially filled with empty cells '.'.

- **Process Each Row:** For each row in the original box:

    - Track the position where the next stone '#' should fall (bottom), starting from the bottom of the column.
    - Traverse the row from right to left:
        - If a stone '#' is encountered, place it at the current bottom position in the rotated matrix and move the bottom position up.
        - If an obstacle '*' is encountered, place it in the rotated matrix and reset the bottom position to just above the obstacle.
- **Return the Rotated Box:** After processing all rows, return the rotated matrix.

```cpp []
#include <vector>
#include <iostream>
#include <cassert>

using std::vector;
using std::cout;
using std::endl;

class Solution {
public:
    /**
     * @brief Rotates the box 90 degrees clockwise.
     * 
     * This function rotates a given box (2D vector of characters) 90 degrees clockwise.
     * Stones ('#') fall to the bottom due to gravity, and obstacles ('*') block the stones.
     * 
     * @param box A 2D vector of characters representing the box.
     * @return A 2D vector of characters representing the rotated box.
     */
    static vector<vector<char>> rotateTheBox(vector<vector<char>>& box) {
        const int r = box.size(), c = box[0].size();
        vector<vector<char>> rotate(c, vector<char>(r, '.'));
        for (int i = 0; i < r; ++i) {
            int bottom = c - 1;
            for (int j = c - 1; j >= 0; --j) {
                if (box[i][j] == '#') {
                    rotate[bottom][r - 1 - i] = '#';
                    bottom--;
                } else if (box[i][j] == '*') {
                    rotate[j][r - 1 - i] = '*';
                    bottom = j - 1;
                }
            }
        }
        return rotate;
    }
};

/**
 * @brief Prints a 2D vector of characters.
 * 
     * This function prints the contents of a 2D vector of characters to the console.
     * 
     * @param vec A 2D vector of characters to be printed.
     */
void print2DVector(const vector<vector<char>>& vec) {
    for (const auto& row : vec) {
        for (const auto& chr : row) 
            cout << chr << " ";
        cout << endl;
    }
}

// Unit test cases
void unitTestCases() {
    vector<vector<char>> res;

    // Test case 1
    vector<vector<char>> box1 = {{'#', '.', '#'}};
    res = Solution::rotateTheBox(box1);
    cout << "Result of the test case 1: " << endl;
    print2DVector(res);
    // Expected result: {{'.'}, {'#'}, {'#'}}
    vector<vector<char>> expected1 = {{'.'}, {'#'}, {'#'}};
    cout << "Expected result of the test case 1: " << endl;
    print2DVector(expected1);
    assert((res == expected1));

    // Test Case 2
    vector<vector<char>> box2 = {{'#', '.', '*', '.'}, {'#', '#', '*', '.'}};
    res = Solution::rotateTheBox(box2);
    cout << "Result of the test case 2: " << endl;
    print2DVector(res);
    // Expected result: {{'#', '.'}, {'#', '#'}, {'*', '*'}, {'.', '.'}}
    vector<vector<char>> expected2 = {{'#', '.'}, {'#', '#'}, {'*', '*'}, {'.', '.'}};
    cout << "Expected result of the test case 2: " << endl;
    print2DVector(expected2);
    assert((res == expected2));

    // Test Case 3
    vector<vector<char>> box3 = {{'#', '#', '*', '.', '*', '.'}, {'#', '#', '#', '*', '.', '.'}, {'#', '#', '#', '.', '#', '.'}};
    res = Solution::rotateTheBox(box3);
    cout << "Result of the test case 3: " << endl;
    print2DVector(res);
    // Expected result: {{'.', '#', '#'}, {'.', '#', '#'}, {'#', '#', '*'}, {'#', '*', '.'}, {'#', '.', '*'}, {'#', '.', '.'}}
    vector<vector<char>> expected3 = {{'.', '#', '#'}, {'.', '#', '#'}, {'#', '#', '*'}, {'#', '*', '.'}, {'#', '.', '*'}, {'#', '.', '.'}};
    cout << "Expected result of the test case 3: " << endl;
    print2DVector(expected3);
    assert((res == expected3));
}

int main() {
    unitTestCases();
    return 0;
}
```
Let's refactor the code 

```cpp []
#include <vector>
#include <iostream>
#include <cassert>

using std::vector;
using std::cout;
using std::endl;

/**
 * @brief Abstract base class for box rotation.
 */
class IBoxRotator {
public:
    /**
     * @brief Pure virtual function to rotate the box.
     * @param box The 2D vector representing the box.
     * @return The rotated 2D vector.
     */
    virtual vector<vector<char>> rotate(const vector<vector<char>>& box) const = 0;
    virtual ~IBoxRotator() = default;
};

/**
 * @brief Concrete class implementing the rotation logic.
 */
class BoxRotator : public IBoxRotator {
public:
    /**
     * @brief Function to rotate the box 90 degrees clockwise.
     * @param box The 2D vector representing the box.
     * @return The rotated 2D vector.
     */
    vector<vector<char>> rotate(const vector<vector<char>>& box) const override {
        const int r = box.size(), c = box[0].size();
        vector<vector<char>> rotated(c, vector<char>(r, '.'));
        for (int i = 0; i < r; ++i) {
            int bottom = c - 1;
            for (int j = c - 1; j >= 0; --j) {
                if (box[i][j] == '#') {
                    rotated[bottom][r - 1 - i] = '#';
                    bottom--;
                } else if (box[i][j] == '*') {
                    rotated[j][r - 1 - i] = '*';
                    bottom = j - 1;
                }
            }
        }
        return rotated;
    }
};

/**
 * @brief Solution class using dependency injection.
 */
class Solution {
private:
    const IBoxRotator& rotator; ///< Reference to the rotator object
public:
    /**
     * @brief Constructor to initialize the rotator reference.
     * @param rotator The rotator object.
     */
    Solution(const IBoxRotator& rotator) : rotator(rotator) {}

    /**
     * @brief Function to rotate the box using the rotator object.
     * @param box The 2D vector representing the box.
     * @return The rotated 2D vector.
     */
    vector<vector<char>> rotateTheBox(vector<vector<char>>& box) const {
        return rotator.rotate(box);
    }
};

/**
 * @brief Class for unit test cases.
 */
class UnitTest {
public:
    /**
     * @brief Function to run all test cases.
     */
    void runTests() const {
        BoxRotator boxRotator;
        Solution solution(boxRotator);

        testCase1(solution);
        testCase2(solution);
        testCase3(solution);
    }

private:
    /**
     * @brief Test case 1: Simple box rotation.
     * @param solution The solution object.
     */
    void testCase1(const Solution& solution) const {
        vector<vector<char>> box1 = {{'#', '.', '#'}};
        vector<vector<char>> res = solution.rotateTheBox(box1);
        cout << "Result of the test case 1: " << endl;
        print2DVector(res);
        vector<vector<char>> expected1 = {{'.'}, {'#'}, {'#'}};
        cout << "Expected result of the test case 1: " << endl;
        print2DVector(expected1);
        assert((res == expected1));
    }

    /**
     * @brief Test case 2: Box with obstacles.
     * @param solution The solution object.
     */
    void testCase2(const Solution& solution) const {
        vector<vector<char>> box2 = {{'#', '.', '*', '.'}, {'#', '#', '*', '.'}};
        vector<vector<char>> res = solution.rotateTheBox(box2);
        cout << "Result of the test case 2: " << endl;
        print2DVector(res);
        vector<vector<char>> expected2 = {{'#', '.'}, {'#', '#'}, {'*', '*'}, {'.', '.'}};
        cout << "Expected result of the test case 2: " << endl;
        print2DVector(expected2);
        assert((res == expected2));
    }

    /**
     * @brief Test case 3: Complex box rotation.
     * @param solution The solution object.
     */
    void testCase3(const Solution& solution) const {
        vector<vector<char>> box3 = {{'#', '#', '*', '.', '*', '.'}, {'#', '#', '#', '*', '.', '.'}, {'#', '#', '#', '.', '#', '.'}};
        vector<vector<char>> res = solution.rotateTheBox(box3);
        cout << "Result of the test case 3: " << endl;
        print2DVector(res);
        vector<vector<char>> expected3 = {{'.', '#', '#'}, {'.', '#', '#'}, {'#', '#', '*'}, {'#', '*', '.'}, {'#', '.', '*'}, {'#', '.', '.'}};
        cout << "Expected result of the test case 3: " << endl;
        print2DVector(expected3);
        assert((res == expected3));
    }

    /**
     * @brief Helper function to print a 2D vector.
     * @param vec The 2D vector to print.
     */
    void print2DVector(const vector<vector<char>>& vec) const {
        for (const auto& row : vec) {
            for (const auto& chr : row) 
                cout << chr << " ";
            cout << endl;
        }
    }
};

/**
 * @brief Main function to run unit tests.
 * @return Exit status.
 */
int main() {
    UnitTest tests;
    tests.runTests();
    return 0;
}
```
['Array', 'Two Pointers', 'Matrix', 'C++']