A clean, modular, and efficient C++ implementation of the Minimum Bracket Reversal problem using a greedy algorithm.
This project was developed as part of my Data Structures and Algorithms course project during my 3rd semester at Amirkabir University of Technology.
Although the problem itself is algorithmic and small in scale, the main goal was to practice and apply fundamental concepts from data structures and algorithms, including greedy strategies, complexity analysis, correctness proofs, and efficient problem solving.
Additionally, this project helped me practice professional software development concepts such as modular C++ architecture, clean code principles, unit testing, and project organization as part of my journey toward becoming a Machine Learning and AI Engineer.
Bracket Reversal is a classic algorithmic problem where the goal is to find the minimum number of bracket reversals required to make an unbalanced bracket sequence valid.
Given a sequence containing only:
(
)
we can reverse individual brackets:
( โ )
or:
) โ (
The objective is to calculate the minimum number of operations needed to create a balanced bracket sequence.
Instead of using extra data structures, this project implements an optimized greedy solution with:
- Single-pass traversal
- Constant extra memory
- Formal correctness analysis
- Modular C++ project structure
The focus of this project is not only solving the problem, but also demonstrating algorithmic thinking and clean software engineering practices.
โก Efficient greedy algorithm
๐ง Single-pass solution
๐ Formal time and space complexity analysis
โ
Correctness proof using mathematical reasoning
๐งฉ Modular C++ architecture
๐๏ธ Separation of interface and implementation
๐งช Automated unit testing
๐ฆ CMake-based build system
๐ Well-documented code
๐ง Easily extensible structure
This project demonstrates the following concepts:
- Data Structures and Algorithms
- Greedy Algorithms
- Algorithm Design
- Invariants
- Correctness Proof
- Complexity Analysis
- String Processing
- Mathematical Reasoning
- Modular Programming
- Separation of Concerns
- Header and Source File Separation
- Unit Testing
- CMake Build System
BracketReversal/
โ
โโโ include/
โ โโโ bracket_reversal.hpp # Function declarations
โ
โโโ src/
โ โโโ main.cpp # Application entry point
โ โโโ bracket_reversal.cpp # Algorithm implementation
โ
โโโ tests/
โ โโโ test_bracket.cpp # Automated tests
โ
โโโ CMakeLists.txt
โโโ LICENSE
โโโ README.md
โโโ .gitignore
The project is divided into independent modules, each responsible for a specific task.
Application entry point.
Responsibilities:
- Receive input from the user
- Call the bracket reversal algorithm
- Display the result
The main function contains no algorithmic logic.
Contains the public interface of the algorithm.
Responsibilities:
- Declare available functions
- Provide communication between different source files
This separates the interface from the implementation.
Contains the core greedy algorithm.
The algorithm maintains:
balance
which represents:
number of '(' - number of ')'
During traversal:
- Opening brackets increase balance.
- Closing brackets decrease balance.
- Negative balance means an unmatched closing bracket exists.
- That bracket must be reversed.
At the end:
- Remaining positive balance represents unmatched opening brackets.
- Half of them need to be reversed.
Contains automated tests.
The tests verify:
- Already balanced sequences
- Only opening brackets
- Only closing brackets
- Mixed invalid sequences
- Empty input
The algorithm processes the string from left to right.
Whenever an unmatched closing bracket appears, it is immediately reversed.
This decision is optimal because:
- A closing bracket without a previous opening bracket can never become valid later.
- Delaying this correction cannot reduce the number of required operations.
If the balance becomes negative during traversal, at least one closing bracket is unmatched.
The balance is defined as:
balance = number of '(' - number of ')'
If:
balance < 0
then:
number of ')' > number of '('
Therefore, there exists an unmatched closing bracket.
Reversing one closing bracket is necessary to restore validity.
Remaining unmatched opening brackets require exactly balance / 2 reversals.
After processing the string:
balance > 0
means there are extra opening brackets.
One operation:
( โ )
reduces the imbalance by 2.
Therefore:
balance / 2
operations are both necessary and sufficient.
The algorithm returns the minimum possible number of reversals.
The algorithm handles all possible imbalance cases:
-
Extra closing brackets:
- Each one requires exactly one reversal.
- The algorithm performs only necessary reversals.
-
Extra opening brackets:
- Each reversal fixes two unmatched opening brackets.
- The algorithm performs exactly the required number.
Therefore, the returned value is optimal.
Let:
n = length of input string
The algorithm scans the input exactly once.
O(n)
Only two integer variables are used:
balance
reversals
No additional data structures are required.
O(1)
Clone the repository:
git clone https://github.com/AradCharon/BracketReversal.gitMove into the project directory:
cd BracketReversalCreate a build directory:
mkdir build
cd buildGenerate build files:
cmake ..Compile the project:
makeRun the executable:
./BracketReversalExample:
Input:
))((
Output:
2
Run:
./BracketReversalTestsExpected output:
All tests passed successfully!
- C++17
- Data Structures & Algorithms
- CMake
- Standard Template Library (STL)
- Git
- GitHub
Through this project, I practiced and improved my understanding of:
- Applying data structures and algorithms concepts in a practical project
- Implementing greedy algorithms learned in coursework
- Designing greedy solutions
- Proving algorithm correctness
- Analyzing time and space complexity
- Writing modular C++ applications
- Separating interface and implementation
- Building projects with CMake
- Writing automated tests
- Organizing professional GitHub repositories
Possible future enhancements include:
-
Adding GoogleTest framework
-
Adding GitHub Actions for Continuous Integration
-
Improving command-line interface
-
Supporting multiple bracket types:
(){}[]
-
Adding benchmark tests for large inputs
-
Creating a reusable bracket validation library
Arad Shafiee
Mathematics & Computer Science Student
Interested in:
- Artificial Intelligence
- Machine Learning
- Data Mining
- Software Engineering
- Algorithms
GitHub:
If you found this project useful or interesting, consider giving it a โญ on GitHub.