Learning the puzzle through code
The assignment deliberately required brute force. At that point in the course, we had not learned the strategies that would come later. We first needed to experience what happens when a program considers almost every possible answer.
I had not played Cyberpunk 2077 yet. The puzzle became interesting through its alternating movement: begin on the top row, then choose from the current column, then the current row, without reusing a cell. That rule made a simple grid unexpectedly tricky.
I knew from the beginning that the search would grow ugly quickly. Every extra buffer position created another level of possible moves.
I considered pruning, but the specification explicitly required brute force. The goal was to implement it, measure it, and understand its limitations so later strategies would feel necessary rather than abstract.
Making a C++ assignment feel like a product
The solver could have remained a terminal program, but a web interface was available as bonus work. I enjoy building websites and wanted to deploy the result, so I created a Next.js application around the C++ binary.
Users could upload or generate a puzzle, inspect the matrix, run the search, and see the selected cells highlighted in order. The interface turned coordinates and scores into something people could understand visually.
This was my first time connecting a native C++ program to a web application. The server passed the board to a spawned binary and waited for JSON output.
Managing serialization, process execution, permissions, operating-system differences, and deployment was more complicated than the algorithm, but it made the project feel complete.
Watching exponential growth happen
On a 10 by 10 board, a buffer size of seven could finish in about one second. Eight took roughly eleven seconds, while nine could take more than a minute.
One extra position multiplied the work. Exponential complexity stopped being notation beside an algorithm and became a loading screen that grew ten times longer.
I experimented with multithreading so independent starting paths could use several CPU cores. Later analysis found that shared best-result state was not synchronized and a missing backtracking step could occasionally miss the optimum.
Experiments do not always work. The attempt taught me that parallelism is not automatically an optimization, and a faster search is useless if shared state makes the answer unreliable.
The most satisfying moment was solving the hardest case provided by the teaching assistant. Seeing the expected answer and its complete path felt like proof that the overall approach worked for the assignment.
I completed the project alone and received the highest score in the class. It was not necessarily the fastest submission, but it was complete: C++, a clear interface, correct required cases, deployment, and detailed documentation.
I would first fix the backtracking and synchronization, then compare the implementation against a simple reference solver through randomized tests. Only after correctness would I add meaningful pruning.
For deployment, I would likely run a TypeScript solver inside a Web Worker. The original project gave me the baseline I needed to understand why smarter strategies matter.
What stayed with me
- Brute force is called brute for a reason.
- Parallel does not automatically mean faster or correct.
- Completeness and presentation can make an algorithm assignment feel like a product.
Run it locally
Clone the source repository or download the project ZIP, then run these commands from the project folder.
Explore the complete project
Download the source, assets, and included documentation as a ZIP archive.
Install and run
$ npm install
$ npm run dev
# open http://localhost:3000
Use it
# Choose TXT FILE and pick a case from test/input, e.g. tc1.txt,
# then press Solve Now. Or choose RANDOM to generate a board:
# buffer 7, 6x6 matrix, 3 sequences, tokens 1C 55 7A BD E9.
# The solver runs in a Web Worker, so no native binary is involved.




